计算机网络

1.1 计算机网络概述

计算机网络是一个将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统。简言之,计算机网络就是一些互联的、自治的、计算机系统的集合。

1.2 计算机网络的组成

从组成部分上看分为硬件、软件、协议从工作方式上看分为边缘部分和核心部分从功能组成上看分为通信子网和资源子网

1.3 计算机网络服务类型

面向连接/无连接有应答/无应答可靠/不可靠

1.4 主机间的通信方式

客户-服务器(C/S)对等(P2P)

1.5 计算机网络体系结构

1.5.1 七层结构(OSI)

物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。这层的传输数据为比特流。数据链路层:主要将从物理层接受的数据进行mac地址(网卡的地址)的封装与解封装。在这一层工作的设备为交换机,这层的数据叫帧。网络层:主要将从数据链路层接受的数据进行IP地址的封装和解封装。这一层工作的设备为路由器,这层的数据叫数据报。传输层:定义了一些传输数据的协议和端口号,如TCP(提供面向连接、可靠的服务),UDP(提供无连接、不可靠的服务)。主要将从网络层接受的数据进行分段传输,到达目的地后进行重组,也即负责向两台主机进程之间的通信提供通用的数据传输服务。这一层的数据叫段。会话层:通过传输层(端口号:传输端口和接收端口)建立数据传输的通路。主要在系统间发起会话或接受会话的请求。表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等操作,也就是把计算机能识别的东西转换成人类能识别的定西。应用层:主要是一些终端应用,例如FTP、Web、DNS应用。

1.5.2 IP层中的各种协议

IP:网际协议 IP 是 TCP/IP体系中两个最主要的协议之一,是TCP/IP体系结构网际层的核心。配套的有: 地址解析协议 ARP(Address Resolution Protocol) 网际控制报文协议 ICMP(Internet Control Message Protocol) 网际组管理协议 IGMP(Internet Group Management Protocol

网际控制报文协议ICMP

(ICMP 很好的讲解 https://blog.csdn.net/baidu_37964071/article/details/80514340)

ICMP 是为了更有效地转发IP数据报和提高交付成功的机会,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。它封装在 IP数据报中,但是不属于高层协议。ICMP 报文分为差错报告报文和询问报文。==Ping 是 ICMP 的一个重要应用,因为走得是网络层,所以不需要端口号,主要用来测试两台主机之间的连通性。==Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送Echo回答报文。Ping会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。

1.5.3 各个层使用的是哪个数据交换设备

网关:应用层、传输层(网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连)路由器:网络层(路由选择、存储转发)交换机:数据链路层、网络层(识别数据包中的 MAC 地址信息,根据 MAC 地址进行转发,并将这些 MAC 地址与对应的端口记录在自己内部的一个地址表中)网桥:数据链路层(将两个 LAN 连起来,根据 MAC 地址来转发帧)集线器(Hub):物理层(纯硬件设备,主要用来连接计算机等网络终端)中继器:物理层(在比特级别对网络信号进行再生和重定时,从而使得它们能够在 网络上传输更长的距离)

1.5.4 各层协议

OSI中的层功能TCP/IP协议族应用层文件传输,电子邮件,文件服务,虚拟终端TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet表示层数据格式化,代码转换,数据加密没有协议会话层解除或建立与别的接点的联系没有协议传输层提供端对端的接口TCP,UDP网络层为数据包选择路由IP,ICMP,RIP,OSPF,BGP,IGMP数据链路层传输有地址的帧以及错误检测功能SLIP,CSLIP,PPP,ARP,RARP,MTU物理层以二进制数据形式在物理媒体上传输数据ISO2110,IEEE802,IEEE802.2

2 数据链路层

2.1 MAC

MAC Address

物理地址、硬件地址,由网络设备制造商生产时写在硬件内部。MAC地址与网络无关,它由厂商写在网卡的BIOS里。

MAC地址通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如:08:00:20:0A:8C: 6D就是一个MAC地址,其中前6位16进制数08:00:20代表网络硬件制造商的编号,它由IEEE分配,而后3位16进制数0A:8C:6D代表该制造商所制造的某个网络产品(如网卡)的系列号。

MAC 地址的作用

由于IP只是逻辑上标识,任何人都随意修改,因此不能用来标识用户;而 MAC地址则不然,它是固化在网卡里面的。从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的。

基于MAC地址的这种特点,局域网采用了用MAC地址来标识具体用户的方法。具体实现:在交换机内部通过“表”的方式把MAC地址和IP地址一一对应,也就是所说的IP、MAC绑定。

具体的通信方式:接收过程,当有发给本地局域网内一台主机的数据包时,交换机接收下来,然后把数据包中的IP地址按照“表”中的对应关系映射成MAC地址,转发到对应的MAC地址的主机上,这样一来,即使某台主机盗用了这个IP地址,但由于他没有这个MAC地址,因此也不会收到数据包。

综上可知,只有IP而没有对应的MAC地址在这种局域网内是不能上网的,于是解决了IP盗用问题。

MAC 地址 ip地址 关系

网络上主机、路由器之间的通信在网络层看来是根据IP地址,路由转发IP数据报的过程。但实际上主机H1的IP数据报(网络层)向下交给数据链路层就被封装成MAC帧从HA1到HA3,然后路由器R1收到MAC帧后,向网络层传输并且解封去掉MAC帧的首部,就能看到IP然后路由器进行路由选择,继续前面的传到数据链路层封装成MAC帧,如此循环直到到达目的主机所在的路由器然后发送给目的主机。(这里是用ARP协议将IP地址转换成MAC地址的)

MAC帧的结构

**帧头:**目的MAC地址、源MAC地址、类型字段(标志上一层使用的是什么协议) **数据部分:**即网络层传下来的IP数据报 **帧尾:**4字节长,包含的信息是帧校验序列(使用CRC校验)

2.1 ARP 协议

地址解析协议ARP

网络层实现主机之间的通信,而链路层实现具体每段链路之间的通信。因此在通信过程中,IP 数据报的源地址和目的地址始终不变,而 MAC 地址随着链路的改变而改变。ARP 为 IP 地址到对应的硬件MAC地址提供动态映射。

ARP 实现由 IP 地址得到 MAC 地址

每个主机都有一个 ARP 高速缓存,里面有本局域网上的各主机和路由器的 IP 地址到 MAC 地址的映射表。先查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。如果主机 A 知道主机 B 的 IP 地址,但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射,此时主机 A 通过广播的方式发送 ARP 请求分主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其MAC 地址,随后主机 A 向其高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射。

ARP攻击的第一步就是ARP欺骗

由上述“ARP协议的工作过程”我们知道,ARP协议基本没有对网络的安全性做任何思考,当时人们考虑的重点是如何保证网络通信能够正确和快速的完成——ARP协议工作的前提是默认了其所在的网络是一个善良的网络,每台主机在向网络中发送应答信号时都是使用的真实身份。不过后来,人们发现ARP应答中的IP地址和MAC地址中的信息是可以伪造的,并不一定是自己的真实IP地址和MAC地址,由此,ARP欺骗就产生了。

ARP 报文的各个字段以及含义?

帧类型:ARP:0x0806 (2)

ARP 首部:

硬件类型:硬件地址的类型,1 表示以太网地址。(2)协议类型:协议地址的类型,0x0800 表示 IP 地址。(2)硬件地址长度:字节为单位 6 (1)协议地址长度:字节为单位 4 (1)操作类型:2 个字节。 ARP 请求 1,ARP 回复 2,RARP 请求 3,RARP 应答 4。(2)发送者硬件地址:6 个字节(6)发送者 IP 地址:4 个字节(4)目标硬件地址:6 个字节(6)目标 IP 地址:4 个字节(4)CRC 校验:4 个字节 (4)

总结: arp 总共 28 个字节。 记忆方法: 以太网先目地后源,ARP 先发送端后目地端。先硬件后协议。

ARP 协议有什么弱点?

1)缓存:主机的地址映射是基于高速缓存的,动态更新的。地址刷新是有时间限制的。 可以通过下次更新之前修改计算机上的地址缓存,造成拒绝服务攻击或者 ARP 欺骗。

2)广播: 攻击者可以伪装 ARP 应答。

3)ARP 应答没有认证,都是合法的。可以在不接受到请求的时候就发出应答包。

ARP 代理的概念和应用场景

若 ARP 请求是从一个网络的主机发送给另一个网络上的主机,那么连接这两个网络的路由器就可以回答该请求,这个过程叫做 ARP 代理。ARP 代理路由器响应 ARP 请求的 MAC 地址为路由器的 MAC 地址而非 ARP 请求的主机的 MAC 地址。

ARP 代理的应用环境:

两个物理网络之间的路由是使用相同的网络号,两个路由器设置成 ARP 代理,实现相互隐瞒物理网络

免费 ARP

免费ARP报文与普通ARP请求报文的区别在于普通的ARP请求报文,其ARP封装内的“目的IP地址”是其他机器的IP地址,而免费ARP的请求报文,其ARP封装内的“目的IP地址”是其自己的IP地址。指主机发送 ARP 查找自己的 IP 地址,即数据链路层 SIP=DIP

作用有两个:

1)免费ARP主要用于检测IP地址冲突。当一台主机发送了免费ARP请求报文后,如果收到了ARP响应报文,则说明网络内已经存在使用该IP 的主机。

2)如果发送免费 ARP 的主机改变了 MAC 地址,可以通过发送免费 ARP 的方式告知其他主机端更新 ARP 表(通知作用)

2.2 MTU

Maximum Transmission Unit,缩写MTU,中文名是:最大传输单元。MTU是数据链路层的概念。MTU限制的是数据链路层的payload,也就是上层协议的大小,例如IP,ICMP等。

MTU有什么用?

举一个最简单的场景,你在家用自己的笔记本上网,用的是路由器,路由器连接电信网络,然后访问了www.baidu.com,从你的笔记本出发的一个以太网数据帧总共经过了以下路径:

笔记本 -> 路由器 -> 电信机房 -> 服务器

其中,每个节点都有一个MTU值,如下:

1500 1500 1500

笔记本 -> 路由器 -> 电信机房 -> 服务器

假设现在我把笔记本的MTU最大值设置成了1700,然后发送了一个超大的ip数据包(2000),这时候在以外网传输的时候会被拆成2个包,一个1700,一个300,然后加上头信息进行传输。

1700 1500 1500

笔记本 -> 路由器 -> 电信机房 -> 服务器

路由器接收到了一个1700的帧,发现大于自己设置的最大值:1500,如果IP包DF标志位为1,也就是不允许分包,那么路由器直接就把这个包丢弃了,根本就不会到达电信机房,也就到不了服务器了,所以,到这里我们就会发现,MTU其实就是在每一个节点的管控值,只要是大于这个值的数据帧,要么选择分片,要么直接丢弃。

为什么是1500?

其实一个标准的以太网数据帧大小是:1518,头信息有14字节,尾部校验和FCS占了4字节,所以真正留给上层协议传输数据的大小就是:1518 - 14 - 4 = 1500,那么,1518这个值又是从哪里来的呢?

假设取一个更大的值

假设MTU值和IP数据包大小一致,一个IP数据包的大小是:65535,那么加上以太网帧头和尾,一个以太网帧的大小就是:65535 + 14 + 4 = 65553,看起来似乎很完美,发送方也不需要拆包,接收方也不需要重组。

那么假设我们现在的带宽是:100Mbps,因为以太网帧是传输中的最小可识别单元,再往下就是0101所对应的光信号了,所以我们的一条带宽同时只能发送一个以太网帧。如果同时发送多个,那么对端就无法重组成一个以太网帧了,在100Mbps的带宽中(假设中间没有损耗),我们计算一下发送这一帧需要的时间:

( 65553 * 8 ) / ( 100 * 1024 * 1024 ) ≈ 0.005(s)

在100M网络下传输一帧就需要5ms,也就是说这5ms其他进程发送不了任何数据。如果是早先的电话拨号,网速只有2M的情况下:

( 65553 * 8 ) / ( 2 * 1024 * 1024 ) ≈ 0.100(s)

100ms,这简直是噩梦。其实这就像红绿灯,时间要设置合理,交替通行,不然同一个方向如果一直是绿灯,那么另一个方向就要堵成翔了。

既然大了不行,那设置小一点可以么?

假设MTU值设置为100,那么单个帧传输的时间,在2Mbps带宽下需要:

( 100 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 ≈ 5(ms)

时间上已经能接受了,问题在于,不管MTU设置为多少,以太网帧头尾大小是固定的,都是14 + 4,所以在MTU为100的时候,一个以太网帧的传输效率为:

( 100 - 14 - 4 ) / 100 = 82%

写成公式就是:( T - 14 - 4 ) / T,当T趋于无穷大的时候,效率接近100%,也就是MTU的值越大,传输效率最高,但是基于上一点传输时间的问题,来个折中的选择吧,既然头加尾是18,那就凑个整来个1500,总大小就是1518,传输效率:

1500 / 1518 = 98.8%

100Mbps传输时间:

( 1518 * 8 ) / ( 100 * 1024 * 1024 ) * 1000 = 0.11(ms)

2Mbps传输时间:

( 1518 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 = 5.79(ms)

总体上时间都还能接受

最小值被限制在64

数据链路层的最小 MTU 为 64 字节。对于 IEEE802.3,两个站点的最远距离不超过 2500m,由 4 个中继器连接而成,其冲突窗口为 51.2us(2 倍电缆传播延迟加上 4 个中继器的双向延迟).对于 10Mbps 的 IEEE802.3 来说,这个时间等于发送 64 字节,即 512 位的时间,64 字节就是由此而来的。如果一个站点已经传输了 512bit,就认为它已经占用了这个信道。

3 网络层

3.1 IP协议

如何理解 IP 的不可靠和无连接。

不可靠:指的是不能保证数据报能成功地到达目的地。发生错误时候,丢弃该数据包,发送 ICMP 消息给信源端。 可靠性由上层提供。无连接:IP 不维护关于后续数据报的状态信息。体现在,IP 数据可以不按顺序发送和接收。A 发送连续的数据报,到达 B 不一定是连续的,来回路由选择可能不一样,路线也不一样,到达先后顺序也不一样。

IP 报文的格式和各个字段的含义。

版本号: IPV4 就是 4,IPV6 就是 6 (4)

**首部长度:**4 个字节为单位。最小为 5,最大为 15。所以最小长度 20 个字节,最大为 60个字节。(4)

服务类型: Qos 用,目前不怎么使用。(8)

**总长度:**字节为单位。 最多可以传送 65535 字节的 IP 数据包。(16)

标识字段(8)

标志 (3)

段偏移(5)与分片有关。

生存时间 TTL:==经过一个路由器减一。 字段为 0 时,数据报被丢弃,并且发送 ICMP 报文通知源主机。==目的是防止数据报在选路时无休止地在网络中流动。(8)

协议:区分上层协议 (8)

首部校验和:仅对首部进行校验。(16)【对比: ICMP,IGMP,TCP,UDP:对首部和数据进行校验】

源地址:(32)

目的地址:(32)

IPv6和IPv4有什么区别?

IPv4用32位的二进制位来表示一台主机的网络地址;而IPv6用128位二进制位来表示一台主机的网络地址。

如何实现IPv6数据报和IPv4数据报之间的兼容?

双协议栈:即让一部分主机(路由)支持双协议(IPv6+IPv4),然后双协议栈主机通过DNS判断目的主机地址是IPv4还是IPv6,如果是IPv6,就打包成IPv6数据报。中间路由转发过程中,如果下一跳的路由是支持IPv4的,那么会把当前的IPv6数据报的首部给转换成IPv4数据报的首部,最后再恢复成IPv6数据报的首部(最后恢复过程中,IPv6数据报首部的某些字段无法恢复,用0填充) 隧道技术:在1Pv6数据报要进入IPv4网络时,把1Pv6数据报封装成为IPv4数据报,当IPv4数据报离开IPv4网络中的隧道时,再把数据部分(即原来的 IPv6数据报)交给主机的1Pv6协议枝。

如何区分多个分片属于同一个IP数据报?

看IP数据报首部的“标志位”和“段偏移”

标志位:主要用于确定有多少个分片。标志字段在IP报头中占3位,第1位作为保留,置0;第2位,分段,有两个不同的取值:该位置0,表示可以分段;该位置1,表示不能分段;第3位,更多分段,同样有两个取值:该位置0,表示这是数据流中的最后一个分段,该位置1,表示数据流未完,后续还有分段,当一个数据报没有分段时,则该位置0,表示这是唯一的一个分段。 当目的主机接收到一个IP数据报时,会首先查看该数据报的标识符,并且检查标志位的第3位是置0或置1,以确定是否还有更多的分段,如果还有后续报文,接收主机则将接收到的报文放在缓存直到接收完所有具有相同标识符的数据报,然后再进行重组。 段偏移:13位的偏移量字段用来表示分段的数据报在整个数据流中的位置,即相当于分片数据报的顺序号。

为什么 IP 首部中要有总长度字段?

因为一些数据链路(以太网)需要填充一些数据以达到最小长度。因为以太网帧的最小长度是 46 个字节+(太网帧头尾大小14 + 4),但是 IP 长度可能更短,所以需要总长度来确定 IP 数据部分的内容。

IP 首部校验和怎么计算的,与 ICMP,IGMP,TCP,UDP 的首部校验和有什么区别与共同点?

(1) 先把校验和字段置 0。

(2) 对首部中每个 16 位比特进行二进制反码求和。

(3) 结果存在检验和字段中。

(4) 收到一份 IP 数据包后,同样对首部中每个 16bit 二进制反码求和。

(5) 最后结果全为 1,表示正确,否则表示错误。

(6) 如果是错误的,IP 就丢弃该数据报,但是不生成差错报文,由上层去处理。

共同点:用到的算法都是一样的。

区别:IP 计算的时候没有将数据包括在内。ICMP,IGMP,TCP,UDP 同时覆盖首部和数据检验码

IP地址分类

A 类地址:首位为 0,1.0.0.1~~126.255.255.254;主机号 24 位B 类地址:首位为 10,128.0.0.1~~191.255.255.254;主机号 16 位C 类地址:首位为 110,192.0.0.1~~223.255.255.254;主机号 8 位D 类地址(多播地址,也叫做组播地址):首位为 1110,224.0.0.1~~239.255.255.254E 类地址:此类地址是保留地址,首位为 11110,240.0.0.1~~254.255.255.254

路由分组转发的过程

路由器在收到IP数据报告后执行的分组转发步骤如下:

从数据报的首部提取目的主机的IP地址D,与本子网的子网掩码相与,得到网络地址N若N就是与本子网的网络地址相匹配, 则进行直接交付(用ARP将目的主机地址D 转换为具体的硬件地址, 把数据报封装为MAC帧, 再发送此帧;否则就是间接交付, 执行 3若本路由表中有目的地址为D的特定主机路由,则把数据报传送给路由表中所指明的下一跳路由器:否则,执行 4若路由表中有到达网络N的路由(采用最长匹配原则选取路由表中每行,将子网掩码与D按位与,获得的网络地址的与路由表中的目的地址一样,可能是直接),则根据gateway和interface找到下一跳的地址,把数据报发送给下一跳:否则,执行 5。若路由表中有一个默认路由, 则把数据报传送给路由表中所指明的默认路由器:否则,执行 6报告转发分组出错

路由表:

IP 路由选择的过程是怎么样的?

根据最长匹配原则,找到条目,发送到指定的路由器。如果不能找到,返回一个“主机不可达”或“网络不可达”的错误。

路由选择协议:

内部网关协议RIP(Routing Information Protocol):RIP是一种分布式的基于距离向量的路由选择协议。 内部网关协议OPSF(Open Shortest Path First):OSPF是使用分布式的链路状态协议。 外部网关协议BGP(Border Gateway Protocol):边界网关协议。

IP 路由选择的特性有什么?

(1) IP 路由选择是逐跳进行的。IP 并不知道到达任何目的的完整路径,只提供下一跳地址。

(2) 为一个网络指定一个路由器,而不是为每个主机指定一个路由器。这样可以缩小路由表规模。

如果路由表中没有默认项,而又没有找到匹配项,这时如何处理?

结果取决于该 IP 数据报是由主机产生的还是被转发的。

如果数据报是由本机产生的,那么就给发送该数据报的应用程序返回一个差错,或者是“主机不可达差错”或者是“网络不可达差错”。

如果是被转发的数据报,就给原始发送一份 ICMP 主机不可达的差错报文。

路由器找到下一跳的网络地址之后,发生了什么?

当路由器收到待转发的数据报,不是将下一跳路由器的 IP 地址填入 IP 数据报,而是送交下层的网络接口软件。网络接口软件使用 ARP 协议 负责将下一跳路由器的 IP 地址转换成硬件地址,并将此硬件地址放在链路层的 MAC 帧的首部,然后根据这个硬件地址找到下一跳路由器。

计算机自动获取IP地址流程

DHCP服务:此服务可以网络中的计算机自动分配IP地址,用户机从DHCP服务器获取IP地址的过程被称为DHCP的租约过程,也就是说此时计算机获得的IP地址不是永久的。一般的租约期限为8天。

一、初次获取IP地址

用户机从DHCP服务器获取IP地址的过程被称为DHCP的租约过程,也就是说此时计算机获得的IP地址不是永久的。一般的租约期限为8天。一台新加入到网络的计算机获取IP地址的过程分为五个步骤。

电脑的操作系统安装了TCP/IP协议栈,这个协议栈包括了一个DHCP客户端进程,首先新加进局域网的用户机向网络中发送discover广播,用于寻找存在于局域网中的DHCP服务器。收到discover广播的DHCP服务器们就在自己的IP地址池中查找是否有合法的IP地址提供给客户机,向网络中的所有用户机发送offer 广播,offer中包含了一个可用的IP地址,可用期限。客户端从响应offer的服务器中选择一个,并在request报文中携带选择的服务器的ip和服务器分配给自己的ip地址。并进行广播,把终端选择的地址和服务器通知网络内所有主机服务器。网络内的服务器收到终端的request请求后,如果是终端选择的服务器,根据的是上面request报文中是否携带自身的信息,比如IP地址。则发送一个广播ACK,确定分配地址等信息;如果不是终端选择的服务,则不响应,并收回分配的地址到可用地址池中。终端收到ack后就把ip地址等信息跟网卡绑定。

二、重新登录

用户机再次登录该局域网时,若IP地址没有过期,那么用户机就会向DHCP服务器发送一个request请求广播,如果该IP地址没有被分配出去那么DHCP服务器会发送一个DHCP ACK的确认信息,此时用户机就可以上网。如果IP地址已经被分配就重复初次获取IP地址的步骤。

三、租约更新的过程

一般的DHCP服务器分配出去的IP地址租约期限为8天,到了第四天客户机就会向DHCP服务器发送续约的请求。所以到了租约期的50%时,就会更新租约。若DHCP服务器无法响应,那么用户机会持续向服务器发送续约请求,直到到期后若服务器依然无响应,那么IP地址会自动释放用户机便无法上网。

NAT和VPN

NAT(网络地址转换协议):将本地内部机器(局域网)通过NAT服务器(至少拥有一个公有IP)与外网通信,NAT服务器通过端口来识别内部机器 VPN(虚拟专用网络协议):路由器将加密后的内网IP数据报封装在外网IP数据报的数据部分,在外网进行传输(即隧道技术)

子网掩码

划分网络号与主机号形式,掩码的意思就是掩盖掉主机号,剩余的就是网络号。

将子网掩码和 IP 地址按位计算 AND,就可得到网络号。

子网掩码还有一个作用,那就是划分子网。

子网划分实际上是将主机地址分为两个部分:子网网络地址和子网主机地址。

形式如下:

未做子网划分的 ip 地址:网络地址+主机地址做子网划分后的 ip 地址:网络地址+(子网网络地址+子网主机地址)

内网和外网到底怎么通信?

公网 IP 和私有 IP 的区别

公有地址(Public address):由 Inter NIC(因特网信息中心)负责。这些 IP 地址分配给注册并向Inter NIC提出申请的组织机构,公有 IP 全球唯一,通过它直接访问因特网(直接能上网)。主要有A、B、C、D、E五类地址:

A类:地址范围是1.0.0.0 到 127.255.255.255,主要分配 给大量主机而局域网网络数量较少的大型网络;

B类:地址范围是128.0.0.0 到191.255.255.255,一般用于国际性大公司和政府机构;

C类:地址范围是192.0.0.0 到223.255.255.255,用于一般小公司校园网研究机构等;

D类:地址范围是224.0.0.0 到 239.255.255.255,用于特殊用途,又称做广播地址;

E类:地址范围是240.0.0.0 到255.255.255.255,暂时保留。

私有地址(Private address):属于非注册地址,专门为组织机构内部使用,说白了,私有 IP 不能直接上网。主要有A、B、C三类,

A类地址范围是10.0.0.0-10.255.255.255 ,

B类地址范围是172.16.0.0-172.31.255.255,

C类地址范围是192.168.0.0-192.168.255.255。

127.0.0.0 到127.255.255.255 为系统环回地址。

而我们平时通过运营商(主要是电信、移动、联通宽带等)上网,通过家用路由器之后,就会变成私有IP,大家可能会疑问,我们可以上网啊,怎么会是私有 IP 呢?

其实我们不是通过私有IP上网的,是通过公有IP。通俗的讲,运营商有公有IP,但是IPV4下IP资源有限,所以这些IP不能每个人分配单独分配一个IP,所以需要动态给上网的用户。 这个过程有点类似于,我们买了一些笔,然后将这些笔分给全班学生使用,当然运行商动态分配公有IP的过程比这个复杂多了。

利用端口映射功能还可以将一台外网IP地址机器的多个端口映射到内网不同机器上的不同端口。

端口映射

端口映射是 NAT 的一种,它将外网主机的 IP 地址的一个端口映射到内网中一台机器,提供相应的服务。当用户访问该 IP 的这个端口时,服务器自动将请求映射到对应局域网内部的机器上。

路由器的两个端口:

WAN:接外部 IP 地址用,通常指的是出口,转发来自内部 LAN 接口的 IP 数据包,这个口的 IP 是唯一的。

LAN:接内部 IP 地址用,LAN 内部是交换机。

NAT

局域网的私网IP地址和互联网的公网地址是通过NAT技术进行转换的。

作用:

有效解决了IPv4地址不足的问题可以隐藏并保护局域网内部计算机,有效避免外部攻击

A 电脑的 IP 是局域网 IP(192.168.31.11),这个 IP(192.168.31.11)是从路由器的 lan口分配的。

当我们上百度的时候,经过路由器的 wan口,进行相应的IP、端口转化:192.168.31.11:80 -> 10.221.0.24:8080,所以,从 wan口出去的地址为:10.221.0.24:8080。

最后,经过运营商,运营商那边会做相应的端口映射(而且是动态端口映射),子网 IP(10.221.0.24:8080)转化为公网 IP(128.0.0.1:8888),通过这个公网 IP 去访问百度服务器。

同理,B 的过程也是一样。通过这样的层层端口映射,最终保证地址(IP + 端口)的唯一性。A 和 B访问百度服务器,尽管它们的局域网 IP 是一样的,但是最终它们访问百度的地址(IP +端口)是唯一的,所以,百度服务器回复时,原路返回时能够区分到底给谁回。

3.2 网际控制报文协议 ICMP

ICMP 的层次和作用。

ICMP 一般认为是在三层的。主要传递一些差错报文和其他需要注意的信息。

问题 2:ICMP 报文的分类?

ICMP 分为两类,一类是 ICMP 查询报文,另一类是 ICMP 差错报文。

改变路由(重定向):路由器把改变路由报文发送给主机, 让主机知道下次应将数据报发送给另外的路由器(可通过更好的路由)回送请求和回答:ICMP回送请求报文是由主机或路由器向一个特定的目的主机发出的询问。 收到此报文的主机必须给源主机或路由器发送ICMP回送回答报文。 这种询问报文用来测试目的站是否可达以及了解其有关状态。时间戳请求和回答:请某台主机或路由器回答当前的日期和时间

问题 3:ICMP 的主机不可达报文是在什么情况下发出的?

三层设备(路由器)给该主机的IP数据报进行分组转发时,没有找到相应路径,向源 IP 发回 ICMP 主机不可达

问题 4:什么情况会导致产生 ICMP 差错报文?

1)ICMP 差错报文。

2)目的地址是广播地址或者多播地址的 IP 数据报。

3)链路层广播的数据报

4)不是 IP 分片的第一片

5)源地址不是单个主机的数据包。

问题 5:ICMP 重定向差错报文是怎么来的,在何种场合出现?

​ 主机 ​ | ​ | —————————————————————— | |

| | R1 R2

1)主机发送 IP 数据报给 R1,因为主机的默认路由指向的下一跳是 R1。

2)R1 收到数据报并且检查它的路由表,发现 R2 是发送该数据报的下一跳。当他将数据报发送给 R2 的时候,发现发送的接口与接受的端口是一样的,因此同时发送一个 ICMP 重定向报文给主机。

3)R1 接受到 ICMP 重定向报文后,接下来的数据报就发送给 R2,而不再发送给 R1。

问题 6:重定向报文有什么规则?

重定向报文只能有路由器生成。

重定向报文是为主机而不是为路由器使用的。

问题 7:Ping 命令的具体过程是怎么样的?

网络层 网络层 网络层

Ping 是 ICMP 的一个重要应用,主要用来测试两台主机之间的连通性。Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送Echo回答报文。Ping会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。

网际控制报文协议——ICMP可以更有效地转发IP数据报和提高交付成功的机会,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。它封装在 IP 数据报中,但是不属于高层协议。ICMP 报文分为差错报告报文和询问报文。

参考文章:《对于 Ping 的过程,你真的了解吗?》https://mp.weixin.qq.com/s/DfQT3Vw2xaq60YIil-7Yxw

4 传输层

4.1 TCP,UDP协议的区别

UDP (用户数据报协议)在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 确是一种最有效的工作方式(一般用于即时通信),比如: QQ 语音、 QQ 视频 、直播等等TCP (传输控制协议)提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的,面向连接的传输服务(TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源),这一难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。

4.2 UDP

4.2.1 UDP实时性为什么好

UDP没有拥塞控制,因此网络中的拥塞也不影响到主机的发送频率。而某些实时应用要求以稳定的速率发送,能容忍一些数据的丢失,但是不允许有较大的时延,而UDP刚好满足这些应用的需求。

4.2.2 UDP数据报的组成

UDP数据报包含两部分,分别是UDP首部和用户数据。整个UDP数据报作为IP数据报的数据部分封装在IP数据报中。UDP首部由8字节组成,分别是4个2字节的字段:

16位源端口号16位目的端口号16位UDP长度16位UDP校验和

UDP可靠传输

RUDP协议

使用UDP实现有序可靠与直接使用TCP的区别是:

可以避免弱网环境下频繁断开连接和握手。弱网环境下TCP延迟可能非常大。UDP比TCP在NAT穿越的场景实现更简单?RUDP可以更方便的使用Relay来优化路径。

RUDP怎么保证可靠性?

通过重传、滑动窗口与拥塞控制等来保证。

TCP 报文首都主要字段含义

源端口和目的端口,各占2个字节,分别写入源端口和目的端口,表示数据从哪个进程来, 到哪个进程去。序号,占4字节。TCP连接中传送的数据流中的每个字节都有一个编号。数据序号字段的值指的是本报文段所发送的数据的第一个字节的序号。确认号(ack),占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;数据偏移(即首部长度),占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远(多少个4字节)。当该字段值为15时,TCP首部达到最大的60字节;保留字段,占6位。保留今后使用,目前置零;紧急位URG,让URG为1时表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应当尽快传送确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;推送PSH,用来提示接收端应用程序立刻将数据从tcp缓冲区读走,这时候就将PSH=1;复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接,我们把含有RST标识的报文称为复位报文段;同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1,我们把含有SYN标识的报文称为同步报文段;终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放,我们把含有FIN标识的报文称为结束报文段;校验和,占两个字节,检验和字段检验的范围包括首部和数据两部分。 由发送端填充, 检验形式有CRC校验等. 如果接收端校验不通过, 则认为数据有问题.。紧急指针字段,占16位,指出本报文段中有多少字节的紧急数据选项字段,长度可变,TCP最初只规定了一种选项,即最大报文段长度——MSS。MSS是TCP报文段中数据字段的最大长度填充字段,为了使首部长度为4字节的整数倍

RST报文

在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。

几种会出现RST的情况

1 端口未打开

服务器程序端口未打开而客户端来连接,最为常见。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求,例如WINDOWS 7 。

比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。

2 请求超时

用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。接收数据超时时,会发送RST包。

3 在一个已关闭的socket上收到数据

如果服务端某个socket已经关闭,但依然收到客户端的数据也会产生RST。

TCP 三次握手

为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。

4.4.1 TCP 三次握手流程

如下图所示,下面的两个机器人通过3次握手确定了对方能正确接收和发送消息(图片来源:《图解HTTP》)。

简单示意图:

客户端–发送带有 SYN 标志的数据包–一次握手–服务端服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端

具体过程:

刚开始, 客户端和服务器都处于 CLOSE 状态.此时, 客户端向服务器主动发出连接请求, 服务器被动接受连接请求.

1, TCP服务器进程先创建传输控制块TCB, 时刻准备接受客户端进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态

2, TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文,此时报文首部中的同步标志位SYN=1, 同时选择一个初始序列号 seq = x, (需要注意的是, 序号并不是从 0 开始的, 而是由发送方随机选择的初始序列号 ( Initial Sequence Number, ISN )开始 )此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定, SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。

3, TCP服务器收到请求报文后, 如果同意连接, 则发出确认报文。确认报文中的 ACK=1, SYN=1, 确认序号是 x+1, 同时也要为自己初始化一个序列号 seq = y, 此时, TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据, 但是同样要消耗一个序号。

4, TCP客户端进程收到确认后还, 要向服务器给出确认。确认报文的ACK=1,确认序号是 y+1,自己的序列号是 x+1。ACK报文段可以携带数据,但如果不携带数据则不消耗序号。在这种情况下,下一个数据报的序号仍然是seq=x+1。

5, 此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

4.4.2 为什么要三次握手

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

所以三次握手就能确认双发收发功能都正常,缺一不可。

为什么不用两次?

为了防止先前已经失效的连接请求报文突然又传送到了服务器,从而产生错误。 如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送的第一个请求连接在网络中滞留,但并且没有丢失。由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前滞留的那一次请求连接,因为网络通畅了, 到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让服务器再次进入到ESTABLISHED状态,但客户端还是CLOSED状态,这将导致不必要的错误和资源的费。 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。 在前两次握手的时候双方都随机选择了自己的初始段序号,并且第二次握手的时候 客户端收到了自己的ACKnumber,确认了自己的序列号,而服务端还没有确认自己的序列号,没有收到ACKnumber, 如果这时候两次握手下就进行数据传递, 序号没有同步,数据就会乱序。

为什么不用四次?

因为三次已经可以满足需要了, 四次就多余了.

4.4.3 第二次握手时回传ACK和SYN的作用

SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号

接收端传回发送端所发送的SYN是为了告诉客户端,我接收到的信息确实就是你所发送的信号。

回传ACK则是为了确认从服务端到客户端的通信

DDos攻击

DDOS本是利用大量的合理请求造成资源过载,占用大量网络资源,导致正常用户服务不可用。

常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。其中SYN flood是一种最为经典的DDOS攻击(SYN洪水攻击)

**SYN flood :**首先伪造大量的源IP地址,分别向服务器端发送大量的SYN包,此时服务器端会返回SYN/ACK包,因为源地址时伪造的,所以伪造的IP并不会应答服务器端没有收到伪造IP的回应,会重试3-5次并且等待一个SYN Time(一般为30秒至2分钟),如果超时则丢弃这个连接。攻击者大量发送这种伪造源地址的SYN求,服务端将会消耗非常多的资源(CPU和内存)来处理这种半连接,同时还要不断地对这些IP进行SYN+ACK重试,最后的结果是服务器无暇理睬正常的连接请求导致拒绝服务。

预防网络层的DDos

**DDos清洗:**需要在运营商网络里进行攻击流量识别,清洗;**CDN加速:**CDN 服务将网站访问流量分配到了各个节点中,这样一方面隐藏网站的真实 IP,另一方面即使遭遇 DDoS 攻击,也可以将流量分散到各个节点中,防止源站崩溃。

TCP 四次挥手

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。==TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。==这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文==(在这之前还需要接受服务器发送的最后的数据)。==服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。

上面讲的比较概括,推荐一篇讲的比较细致的文章:https://blog.csdn.net/qzcsu/article/details/72861891

为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

web服务器只开启了一个端口,他是如何为多用户服务的?

TCP套接字的唯一标识是一个五元组(源IP地址,源端口号,目的IP地址,目的端口号,协议)

多个不同的套接字可以拥有相同的目的端口号80,由于源ip或端口号不同,TCP套接字就可以唯一标识,通信就可以进行。同时,一个端口号只能被一个进程所监听。

listen函数接收客户端的连接请求,accept函数把建立好连接的socket从就绪队列拿出一个,如果就绪队列为空(没有就绪连接) 则会阻塞。

注意:端口是用来区分应用的,而不是区分连接!!!

服务器端和客户端TCP最大长连接数量的区别

服务器:server通常固定在某个本地端口上监听,等待client的连接请求,所以五元组中后三个是固定的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。

**客户端:**client每次发起tcp连接请求时,除非绑定端口,通常会让系统选取一个空闲的本地端口(local port),该端口是独占的,不能和其他tcp连接共享。因为tcp首部port字段16位,所以普通服务只有65536 - 1024个端口可用(0-1023保留为知名服务端口)。在计算资源够的情况下,可以保持 64512 个长连接。

服务器出现大量的CLOES_WAIT状态

服务端进入了CLOSE_WAIT状态说明服务器端已经到了响应客户端关闭时请求的FIN, 但还没有发出自己的FIN。

**解决办法:**一般是因为代码不严谨,服务端阻塞在某个操作上。

TIME-WAIT状态的作用,为什么客户端最后还要等待2MSL?

MSL(最大分段寿命),即一个 TCP 分段可以存在于互联网系统中的最大时间,TCP允许不同的实现可以设置不同的MSL值。通常为4分钟

第一,保证客户端发送的最后一个ACK报文能够到达服务器,如果ACK报文丢失,服务器又会重新发送一次FIN+ACK报文请求断开,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在下次连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

如何优化TCP连接中产生的大量的TIME_WAIT的状态?

在高并发短连接的TCP服务器上,服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。

主动关闭连接的一方才会产生TIME_WAIT

一些爬虫服务器或者WEB服务器,(如果在安装的时候没有做内核参数优化的话)上经常会遇到这个问题

统计TIME-WAIT状态

第一种使用netstat(性能一般)

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

LAST_ACK 14

SYN_RECV 348

ESTABLISHED 70

FIN_WAIT1 229

FIN_WAIT2 30

CLOSING 33

TIME_WAIT 18122

状态:描述

CLOSED:无连接是活动的或正在进行

LISTEN:服务器在等待进入呼叫

SYN_RECV:一个连接请求已经到达,等待确认

SYN_SENT:应用已经开始,打开一个连接

ESTABLISHED:正常数据传输状态

FIN_WAIT1:应用说它已经完成

FIN_WAIT2:另一边已同意释放

ITMED_WAIT:等待所有分组死掉

CLOSING:两边同时尝试关闭

TIME_WAIT:另一边已初始化一个释放

LAST_ACK:等待所有分组死掉

第二种使用ss命令(性能较高)

ss -s

显示:

Total: 4122 (kernel 0)

TCP: 37241 (estab 3157, closed 33193, orphaned 858, synrecv 0, timewait 33176/0), ports 0

Transport Total IP IPv6

* 0 - -

RAW 1 1 0

UDP 4 4 0

TCP 4048 4048 0

INET 4053 4053 0

FRAG 0 0 0

可以看到timewait的链接有3万多个

TIME_WAIT过多的危害

TCP 本地端口数量,上限为 65535(6.5w),这是因为 TCP 头部使用 16 bit,存储「端口号」,因此约束上限为 65535。

(1)服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。

(2)由于TIME-WAIT状态的连接存在,服务器进程无法立即重启,因为端口被占用的问题。(双十一,Tmall服务器)

(3)占一定的内存,一个4k(但不是主要危害)

解决办法:

Linux下time-wait的优化:

net.ipv4.tcp_tw_reuse = 1 socket重用:允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;如果新的时间戳比之前TIME_WAIT连接的时间戳大的话(大于1s),则可直接复用原有的TIME_WAIT连接。即:TIME-WAIT状态的连接,仅仅1秒后就可以被重用了。 net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间

服务器重启的优化:

可设置套接字选项为SO_REUSEADDR,该选项的意思是,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,并且套接字选项为SO_REUSEADDR,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。

TCP 协议如何保证可靠传输

应用数据被分割成 TCP 认为最适合发送的数据块。TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。TCP 的接收端会丢弃重复的数据。流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)拥塞控制: 当网络拥塞时,减少数据的发送。ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

1 校验和

计算方式:在数据传输的过程中,将发送的数据段都当做一个16位的整数。将这些整数加起来。并且前面的进位不能丢弃,补在后面,最后取反,得到校验和。

发送方:在发送数据之前计算检验和,并进行校验和的填充。

接收方:收到数据后,对数据以同样的方式进行计算,求出校验和,与发送方的进行比对。

注意:如果接收方比对校验和与发送方不一致,那么数据一定传输有误。但是如果接收方比对校验和与发送方一致,数据不一定传输成功。

2 确认应答与序列号

序列号:TCP传输时将每个字节的数据都进行了编号,这就是序列号。 确认应答:TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。

序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是TCP传输可靠性的保证之一。

3 超时重传

重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传。

TCP 会在以下两种情况发生超时重传:

数据包丢失确认应答丢失

RTT(Round-Trip Time 往返时延),从下图我们就可以知道:

RTT 就是数据从网络一端传送到另一端所需的时间,也就是包的往返时间。

超时重传时间是以 RTO (Retransmission Timeout 超时重传时间)表示。

当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差; 当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。

超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。

3 ARQ协议

自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认报文,它通常会重新发送。ARQ包括停止等待ARQ协议和连续ARQ协议。

停止等待ARQ协议

停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认(回复ACK)。如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组;在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认;

优点: 简单

缺点: 信道利用率低,等待时间长

1) 无差错情况:

发送方发送分组,接收方在规定时间内收到,并且回复确认.发送方再次发送。

2) 出现差错情况(超时重传):

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续 ARQ 协议 可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。

由于TCP传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。

在Linux中(BSD Unix和Windows下也是这样)超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

3) 确认丢失和确认迟到

确认丢失 :确认消息在传输过程丢失。当A发送M1消息,B收到后,B向A发送了一个M1确认消息,但却在传输过程中丢失。而A并不知道,在超时计时过后,A重传M1消息,B再次收到该消息后采取以下两点措施:1. 丢弃这个重复的M1消息,不向上层交付。 2. 向A发送确认消息。(不会认为已经发送过了,就不再发送。A能重传,就证明B的确认消息丢失)。确认迟到 :确认消息在传输过程中迟到。A发送M1消息,B收到并发送确认。在超时时间内没有收到确认消息,A重传M1消息,B仍然收到并继续发送确认消息(B收到了2份M1)。此时A收到了B第二次发送的确认消息。接着发送其他数据。过了一会,A收到了B第一次发送的对M1的确认消息(A也收到了2份确认消息)。处理如下:1. A收到重复的确认后,直接丢弃。2. B收到重复的M1后,也直接丢弃重复的M1。

连续ARQ协议

连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。

优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。

缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5条 消息,中间第三条丢失(3号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。

回退n帧ARQ可以看做是滑动窗口协议,这就是说接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。

但网络状况不好的时候会出现,如发送窗口为 10 时,一次发送 10 个数据包,前面两个正确返回了,但第三个丢失了,这时发送方就得重新从第三个包开始,把后面的再传一遍,接收方发现前面的 3 - 10 这几个帧失序并丢弃,所以网络不佳的情况下可能会比停止等待ARQ还慢。

滑动窗口:

发送端和接收端分别设定发送窗口和接收窗口。三次握手的时候,客户端把自己的缓冲区大小也就是窗口大小发送给服务器,服务器回应是也将窗口大小发送给客户端,服务器客户端都知道了彼此的窗口大小。比如主机A的发送窗口大小为5,主机A可以向主机B发送5个单元,如果B缓冲区满了,A就要等待B确认才能继续发送数据。如果缓冲区中有1个报文被进程读取,主机B就会回复ACK给主机A,接收窗口向前滑动,报文中窗口大小为1,就说明A还可以发送1个单元的数据,发送窗口向前滑动,之后等待主机B的确认报文。只有接收窗口向前滑动并发送了确认时,发送窗口才能向前滑动。

例子:

4 滑动窗口和流量控制

TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据,并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。

注:16位的窗口大小最大能表示65535个字节(64K),但是TCP的窗口大小最大并不是64K。在TCP首部中40个字节的选项中还包含了一个窗口扩大因子M,实际的窗口大小就是16为窗口字段的值左移M位。每移一位,扩大两倍。

5 拥塞控制

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

为了进行拥塞控制,TCP 发送方要维持一个拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

TCP的拥塞控制采用了四种机制,即 慢启动 、 拥塞避免 、快重传 和 快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。

慢启动: 慢启动算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd初始值为1,每经过一个传播轮次,cwnd加倍。拥塞避免: 拥塞避免算法的思路是让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送放的cwnd加1.

为了防止 cwnd 增长过大引起网络拥塞,设置一个慢开始阈值(ssthresh 状态变量)

当 cwnd<ssthresh,使用慢开始算法

当 cwnd=ssthresh,既可使用慢开始算法,也可以使用拥塞避免算法

当 cwnd>ssthresh,使用拥塞避免算法

拥塞发生

当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:

超时重传快速重传

发生超时重传的拥塞发生算法 就把慢开始阈值设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为 1,执行慢开始算法。 如图所示:

快重传与快恢复: 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。==有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认信息指定的数据段丢失了,并立即重传这些丢失的数据段,==就执行“乘法减小”算法,把 ssthresh 门限减半,但是接下去并不执行慢开始算法,而是将 cwnd 设置为 ssthresh 的大小,然后执行拥塞避免算法。

有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。

为什么发生拥塞时,ssthresh 是变为1/2 ?

因为如果连接是稳定运行的,并且出现了丢包,这可能是因为一个新的连接启动并占用了你的一些带宽。你应该将窗口减少一半,因为你可用的带宽已经减少了一半。而且,如果有两个以上的连接共享带宽,则将窗口减半是保守的——在高流量密集时保持保守可能是明智的。

tcp粘包是怎么产生的?

1、什么是 tcp 粘包?

发送方发送的多个数据包,到接收方缓冲区首尾相连,粘成一包,被接收。

2、原因

(1)发送方原因

TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:

只有上一个分组得到确认,才会发送下一个分组收集多个小分组,在一个确认到来时一起发送

(2)接收方原因

TCP接收到数据包时,并不会马上交到应用层进行处理,而是接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。

3、处理方法

(1)发送方

对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。

(2)接收方

接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。

(2)应用层

应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。

解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢?

格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。

UDP会不会产生粘包问题呢?

TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。

UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。

举个例子:有三个数据包,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存有12k的大小,就可以一次把这3个数据包全部发送完毕。

5 应用层

5.1 DNS

5.1.1 DNS协议

域名解析协议,www.xxx.com 转换成 ip,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 ip 地址,也提供逆向从IP地址反查域名的服务。

DNS 协议运行在 UDP 协议之上,使用端口号 53

为什么不用域名来直接进行通信呢?

因为IP地址是固定长度的,IPv4是32位,IPv6是128位,而域名是变长的,不便于计算机处理。IP地址对于用户来说不方便记忆,但域名便于用户使用,例如www.baidu.com这是百度的域名。

总结一点就是IP地址是面向主机的,而域名则是面向用户的。

hosts文件

域名和IP的对应关系保存在一个叫hosts文件中。最初,通过互联网信息中心来管理这个文件,如果有一个新的计算机想接入网络,或者某个计算IP变更都需要到信息中心申请变更hosts文件。其他计算机也需要定期更新,才能上网。但是这样太麻烦了,就出现了DNS系统。

5.1.2 DNS 系统

一个组织的系统管理机构, 维护系统内的每个主机的IP和主机名的对应关系如果新计算机接入网络,将这个信息注册到数据库中用户输入域名的时候,会自动查询DNS服务器,由DNS服务器检索数据库,得到对应的IP地址我们可以通过命令查看自己的hosts文件:

在域名解析的过程中仍然会优先查找hosts文件的内容。

5.1.3 DNS理论知识

一、DNS域名结构

1、域名的层次结构

域名系统必须要保持唯一性。为了达到唯一性的目的,因特网在命名的时候采用了层次结构的命名方法:

每一个域名(本文只讨论英文域名)都是一个标号序列(labels),用字母(A-Z,a-z,大小写等价)、数字(0-9)和连接符(-)组成标号序列总长度不能超过255个字符,它由点号分割成一个个的标号(label)每个标号应该在63个字符之内,每个标号都可以看成一个层次的域名。级别最低的域名写在左边,级别最高的域名写在右边。

域名服务主要是基于UDP实现的,服务器的端口号为53。关于域名的层次结构,如下图所示:

eg :我们熟悉的,www.baidu.com

com: 一级域名. 表示这是一个企业域名。同级的还有 “net”(网络提供商), “org”(⾮非盈利组织) 等。baidu: 二级域名,指公司名。www: 只是一种习惯用法。

2、域名的分级 域名可以划分为各个子域,子域还可以继续划分为子域的子域,这样就形成了顶级域、二级域、三级域等。如下图所示:

其中顶级域名分为:国家顶级域名、通用顶级域名、反向域名。

国家顶级域名中国:cn, 美国:us,英国uk…通用顶级域名com公司企业,edu教育机构,gov政府部门,int国际组织,mil军事部门 ,net网络,org非盈利组织…反向域名arpa,用于PTR查询(IP地址转换为域名)

二、域名服务器

域名是分层结构,域名服务器也是对应的层级结构。

有了域名结构,还需要有一个东西去解析域名,域名需要由遍及全世界的域名服务器去解析,域名服务器实际上就是装有域名系统的主机。

由高向低进行层次划分,可分为以下几大类:

分类作用根域名服务器最高层次的域名服务器,本地域名服务器解析不了的域名就会向其求助顶级域名服务器负责管理在该顶级域名服务器下注册的二级域名权限域名服务器负责一个区的域名解析工作本地域名服务器当一个主机发出DNS查询请求时,这个查询请求首先发给本地域名服务器

注:一个域名服务器所负责的范围,或者说有管理权限的范围,就称为区

我们需要注意的是:

每个层的域名上都有自己的域名服务器,最顶层的是根域名服务器 每一级域名服务器都知道下级域名服务器的IP地址 为了容灾, 每一级至少设置两个或以上的域名服务器

三、域名解析过程

当一个用户在地址栏输入www.taobao.com时,DNS解析有大致十个过程:

浏览器先检查自身缓存中有没有被解析过的这个域名对应的ip地址,如果有,解析结束。同时域名被缓存的时间也可通过TTL属性来设置。如果浏览器缓存未命中,浏览器会检查操作系统缓存中有没有对应的已解析过的结果。而操作系统也有一个域名解析的过程。在windows中可通过c盘里一个叫hosts的文件来设置,如果你在这里指定了一个域名对应的ip地址,那浏览器会首先使用这个ip地址。如果至此还没有命中域名,才会真正的请求本地域名服务器(LDNS)来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远,并且这台服务器的性能都很好,一般都会缓存域名解析结果,大约80%的域名解析到这里就完成了。如果LDNS仍然没有命中,就直接跳到Root Server 域名服务器请求解析根域名服务器返回给LDNS一个所查询域的主域名服务器(gTLD Server,国际顶尖域名服务器,如.com .cn .org等)地址此时LDNS再发送请求给上一步返回的gTLD接受请求的gTLD查找并返回这个域名对应的Name Server的地址,这个Name Server就是网站注册的权限域名服务器本地域名服务器向权限服务器进行查询Name Server根据映射关系表找到目标ip,返回给LDNSLDNS缓存这个域名和对应的ip,把解析的结果返回给用户,用户根据TTL值缓存到本地系统缓存中,域名解析过程至此结束

5.1.4 DNS劫持

通过攻击DNS服务器或者伪造DNS服务器,把目标网站域名解析到错误的IP地址从而实现用户无法访问目标网站或进行其它恶意行为。

传统的基于 UDP 协议的公共 DNS 服务极易发生 DNS 劫持

解决方案:

域名解析请求直接发送到HTTPDNS服务端,从而绕过运营商的本地DNS(相当于本地域名服务器) 通过代理绕过运行商本地DNS

修改主机的dns服务器地址相当于修改了本地域名服务器

如何判断DNS劫持?

把DNS改成公网DNS 8.8.8.8,如果能正常上网就说明原来发生了DNS劫持QQ能上网,网页不行?

5.2 URI 和 URL

URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。 URL(Uniform Resource Location) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。

URI的作用像身份证号一样,URL的作用更像家庭住址一样。URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。

5.3 HTTP

1 各种协议与HTTP协议之间的关系

2 请求报文和响应报文格式

请求报文

格式:

案例:

POST /search HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,

application/msword, application/x-silverlight, application/x-shockwave-flash, */*

Referer: http://www.google.cn/

Accept-Language: zh-cn

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)

Host: www.google.cn

Connection: Keep-Alive

Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;

NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-

FxlRugatx63JLv7CWMD6UB_O_r

hl=zh-CN&source=hp&q=domety

请求行

请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。

HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。

请求头

请求头部由键/值对组成,每行一对,键和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息

典型的常用请求头有:

User-Agent:产生请求的客户端类型。

Accept:客户端可识别的内容类型列表。

Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。

Accept-Encoding: 客户端使用的编码环境和编码方式

Accept-Language: 客户端语言环境

Authorization:授权信息,一般用于存放授权之后的信息

Connection:表示是否需要持久连接

Content-Length:表示请求数据正文的长度

Cookie:这个与服务器端做交互的,存储保持会话的重要信息 Referer:表示该次请求的来源,一般用于做防盗链

Content-Type字段类型

raw 原始类型,比如json、xmlapplication/x-www-form-urlencoded,会将表单内的数据转换拼接成 key-value 对multipart/form-data,将表单的数据处理为一条消息,以标签为单元,用分隔符分开

换行符

CR+LF

请求体

请求体通常不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。

响应报文

格式:

案例:

HTTP/1.1 200 OK

Date: Mon, 23 May 2005 22:38:34 GMT

Content-Type: text/html; charset=UTF-8

Content-Encoding: UTF-8

Content-Length: 138

Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT

Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)

ETag: "3f80f-1b6-3e1cb03b"

Accept-Ranges: bytes

Connection: close

An Example Page

Hello World, this is a very simple HTML document.

状态行

状态行由HTTP协议的版本、响应状态代码和状态代码的文本描述3个字段组成,它们用空格分隔。例如,HTTP/1.1 200 OK。

状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。

常见的状态码及其描述:

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。 2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

**200 OK:**客户端请求成功。**204 No Content:**表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);**206 Partial Content:**应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。 3xx 类状态码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。

**301 Moved Permanently:**永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL; **302 Found:**表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。 301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。 **304 Not Modified:**不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。(etag、if-none-match) 4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。

**400 Bad Request:**客户端请求报文有语法错误,不能被服务器所理解。**401 Unauthorized:**请求未经许可,需要通过HTTP认证;这个状态代码必须和WWW-Authenticate报头域一起使用。**403 Forbidden:**服务器拒绝该次访问(服务器的访问权限出现问题,比如文件或目录的权限问题)**404 Not Found:**请求资源不存在,举个例子:输入了错误的URL。 5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。

**500 Internal Server Error:**服务器发生未知的错误(这是一个笼统的错误码)。**503 Server Unavailable:**服务器暂时处于超负载或正在进行停机维护,无法处理请求;

响应头

响应头部与请求头部类似,为响应报文添加了一些附加信息,例如:

Content-Type:响应正文的类型(是图片还是二进制字符串)Content-Charset:响应正文使用的编码Content-Language:响应正文使用的语言

http状态码301和302详解及区别

301 redirect: 301 代表永久性转移(Permanently Moved)302 redirect: 302 代表暂时性转移(Temporarily Moved )

301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

http 常见字段有哪些

Host客户端发送请求时,用来指定服务器的域名。有了 Host 字段,就可以将请求发往「同一台」服务器上的不同网站。

Content-Lengt服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。

Connection 用于表示本次连接采取的是长连接还是短连接。

Content-Type 用于服务器回应时,告诉客户端,本次数据是什么格式。

Accept 客户端请求的时候,声明自己可以接受哪些数据格式。

Content-Encoding 说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式 (gzip)

4 HTTP长连接,短连接

在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。

而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:

Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

典型应用场景:

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。数据库的连接用长连接。短链接多用于WEB网站的http服务,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源。并发量大,但每个用户无需频繁操作情况下需用短连好。

5 HTTP是不保存状态的协议,如何保存用户状态?

HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们保存用户状态呢?

cookie和Session 机制的存在就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个Session)。

在服务端保存 Session 的方法很多,最常用的就是内存和数据库(比如是使用内存数据库redis保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。

Cookie 被禁用怎么办?

最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。

6 Cookie和Session

5.3.7.1 Cookie

简述Cookie

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

简述Cookie的设置和发送过程

用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,包含Set-Cookie这个头部,当然这些信息并不是存放在HTTP响应体 (Response Body)中的,而是存放于HTTP响应头(Response Header)客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings[用户名]\Cookies目录中找到存储的Cookie;客户端再次向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(equest Header)了。

简述Set-Cookie的意义

当服务器返回给客户端一个Http响应信息时,其中如果包含Set-Cookie这个头部,说明:

指示客户端建立一个Cookie在后续的Http请求中自动发送这个Cookie到服务器端,直到这个Cookie过期。如果Cookie的生存时间是整个会话期间的话,那么浏览器会将 Cookie保存在内存中, 浏览器关闭时就会自动清除这个Cookie。如果将Cookie保存在客户端的硬盘中,浏览器关闭的话,该Cookie 也不会被清除,下次打开浏览器访问对应网站时,这个Cookie就会自动再次发送到服务器端。

简述Cookie的其他特性

Cookie具有不可跨域名性。 根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。 Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。Cookie不支持中文,需要编码

5.3.7.2 Session

简述Session

Session是一种记录客户状态的机制,不同于Cookie的是Cookie保存在客户端浏览器中,而==Session保存在服务器上。==客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

简述Session的创建与使用过程

Session在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。 创建Session的同时,服务器会为该Session生成唯一的session id, 这个session id在随后的请求中会被用来重新获得已经创建的Session。

Session被创建之后,就可以调用Session相关的方法往Session中增加内容了, 而这些内容只会保存在服务器中,发到客户端的只有session id。可以通过HttpServletRequest对象的getSession方法获得HttpSession。 通过HttpSession的setAttribute方法可以将一个值放在HttpSession中, 通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。

当客户端再次发送请求的时候,会将这个session id带上,服务器接受到请求之后就会依据session id找到相应的Session,从而再次使用Session。

简述Session的生命周期

Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存中。每个用户都会有一个独立的Session。这个Session使用一个Session ID来标识这个Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。

Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。 如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。

Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。

例如,当浏览器第二次发送请求,会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的Session。

由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。

简述Session如何传递Session id

保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器 由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id 另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器

Session和Cookie的区别

安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。 有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。

Session和Cookie的应用场景

Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。

Cookie 一般用来保存用户信息 比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。

Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。

Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。

7 如何保证Cookie的安全性,比如你的cookies被拷贝了?

设置Cookie的有效期不要太长设置HTTPOnly属性为true设置复杂的Cookie并加密:cookie的key使用uuid,随机生成;cookie的value可以使用复杂组合用户第一次登录时,保存ip+cookie加密后的token同时使用Session和Cookie如果网站支持https,尽可能使用https

8 简述Cookie被禁用的解决办法

最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。

9 关于Token

(Access)Token是访问资源接口(API)时所需要的资源凭证,每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里

基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库

refresh token用来更新access token

10 Get和Post区别

标准答案:

**参数位置:**GET会将参数暴露在url上,某种程度上不安全,而POST将参数放在Request body中**长度限制:**理论上GET是没有长度限制的,但一般浏览器会对url的参数长度有限制(IE:2083个字节);理论上POST在Request body没有长度、数量限制,但是服务器端一般会做限制(Tomcat:maxPostSize默认为2M,设置为0则不限制大小)**参数保存:**GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留GET只能进行url编码,而POST可以支持多种编码方式GET请求会被浏览器主动cache,而POST不会,除非手动设置GET在浏览器回退时是无害的,而POST会再次提交请求

加分答案:

GET和POS本质上都是TCP连接,上述区别的根本原因在于,HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。例如,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。如果在GET的Request Body中偷带数据,但是不保证该数据会被处理。

此外==,GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把httpheader和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)==。

因此,应该注意: GET与POST都有自己的语义,不能随便混用。 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

应用场景

post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作(淘宝,支付宝的搜索查询都是get提交),目的是资源的获取,读取数据get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;

11 HTTP 传输大文件

一、数据压缩

通常浏览器在发送请求时都会带着“Accept-Encoding”头字段,里面是浏览器支持的压缩格式列表,例如gzip、deflate、br等,这样服务器就可以从中选择一种压缩算法,放进“Content-Encoding”响应头里,再把原数据压缩后发给浏览器。

缺点:gzip等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用gzip处理也不会变小(甚至还有可能会增大一点),所以它就失效了。

二、分块传输

大文件分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原。

这种“化整为零”的思路在HTTP协议里就是“chunked”分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的body部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送。

分块传输也可以用于“流式数据”,例如由数据库动态生成的表单页面,这种情况下body数据的长度是未知的,无法在头字段“Content-Length”里给出确切的长度,所以也只能用chunked方式分块发送。

Transfer-Encoding: chunked和Content-Length这两个字段是互斥的,也就是说响应报文里这两个字段不能同时出现,一个响应报文的传输要么是长度已知,要么是长度未知(chunked)。

分块传输的编码规则:

1)每个分块包含两个部分,长度头和数据块;

2)长度头是以CRLF(回车换行,即\r\n)结尾的一行明文,用16进制数字表示长度;

3)数据块紧跟在长度头后,最后也用CRLF结尾,但数据不包含CRLF;

4)最后用一个长度为0的块表示结束,即“0\r\n\r\n”。

客户端缓存

强缓存

cache-control: max-age=xxxx

expire

协商缓存

etag/if-none-match

last-modified/if-modified-since

HTTP 1.0和HTTP 1.1的主要区别

方法不同,HTTP 1.0 只有GET、POST、HEAD方法,HTTP 1.1 增加了OPTIONS、DELETE、HOST等方法HTTP 1.1 引入长连接,TCP连接默认不关闭,可以被多个请求复用;而HTTP 1.0 默认每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接,不过也可以通过设置非标准字段Connection: keep-alive来实现长连接HTTP 1.1 引入管道机制,在同一个TCP连接里面,客户端可以同时发送多个请求,改进了HTTP协议的效率,HTTP 1.0 一次只能发送一个请求HOST头域,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名;HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)Range头域,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP/1.1新增Range头域,可以支持请求数据部分内容,比如迅雷中的支持多线程下载,每个线程下载部分内容,来加快传输,可以实现带宽优化

Http 2.0 和 Http1.1 的区别

头部压缩 HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。 这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。 二进制格式 HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。增加了数据传输的效率。 多路复用 HTTP/2 是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。 移除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,大幅度提高了连接的利用率。 举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。 服务器推送 HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。 举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JS、CSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫 Cache Push)。

HTTP/2 有哪些缺陷?HTTP/3 做了哪些优化?

HTTP/2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。

HTTP/1.1 中的管道( pipeline)传输中如果有一个请求阻塞了,那么队列后请求也统统被阻塞住了 HTTP/2 多个请求复用一个TCP连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。

这都是基于 TCP 传输层的问题,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP!

UDP 发生是不管顺序,也不管丢包的,所以不会出现 HTTP/1.1 的队头阻塞 和 HTTP/2 的一个丢包全部重传问题。

大家都知道 UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。

QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响。TLS3 升级成了最新的 1.3 版本,头部压缩算法也升级成了 QPack。HTTPS 要建立一个连接,要花费 6 次交互,先是建立TCP三次握手,然后是 TLS/1.3 的三次握手。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 3 次,减少了交互次数。

所以, QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议。

QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题。所以 HTTP/3 现在普及的进度非常的缓慢,不知道未来 UDP 是否能够逆袭 TCP。

14 HTTP 2.0 多路复用

图中第一种请求方式,就是单次发送request请求,收到response后再进行下一次请求,显示是很低效的。

于是http1.1提出了管线化(pipelining)技术,就是如图中第二中请求方式,一次性发送多个request请求。

然而pipelining在接收response返回时,也必须依顺序接收,如果前一个请求遇到了阻塞,后面的请求即使已经处理完毕了,仍然需要等待阻塞的请求处理完毕。这种情况就如图中第三种,第一个请求阻塞后,后面的请求都需要等待,这也就是队头阻塞(Head of line blocking)。

为了解决上述阻塞问题,http2中提出了多路复用(Multiplexing)技术。http2中将多个请求复用同一个tcp链接中,将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。也就是将每个request-response拆分为了细小的二进制帧Frame,这样即使一个请求被阻塞了,也不会影响其他请求,如图中第四种情况所示。

15 HTTP Request 和 HTTP Response 分别在tcp socket什么阶段发送

**不论是短连接还是长连接:**request 报文和 response在三次握手建立连接后的established状态发送

16 一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断?

短连接:一般是web服务器发回response后主动关闭连接(如NGINX未开启keep-alive )

长连接:开启keep-alive ,配置keepalive_timeout 65;如果客户端在这个时间内没有新的请求,那么到时间后由服务端主动断开。

另外:在浏览器tab关闭时,tcp连接会关闭。

网页中的图片资源为什么分放在不同的域名下?

浏览器对并发请求的数目限制是针对域名的,即针对同一域名(包括二级域名)在同一时间支持的并发请求数量的限制(Chrome允许对同一Host域名建立6个TCP连接)。如果请求数目超出限制,则会阻塞。因此,网站中对一些静态资源,使用不同的一级域名,可以提升浏览器并行请求的数目,加速界面资源的获取速度。

如果HTTP请求丢包了多路复用还有用吗

没用

说一下转发(Forward)和重定向(Redirect)的区别

转发是服务器行为,重定向是客户端行为。

转发(Forword) 通过RequestDispatcher对象的 forward(HttpServletRequest request,HttpServletResponse response) 方法实现的。 RequestDispatcher 可以通过 HttpServletRequest的 getRequestDispatcher() 方法获得。例如下面的代码就是跳转到 login_success.jsp 页面。

重定向(Redirect) 是利用服务器返回的状态吗来实现的。客户端浏览器请求服务器的时候,服务器会返回一个态码。服务器通过HttpServletRequestResponse的setStatus(int status)方法设置状态码。如果服务器返回301或者302,则浏览器会到新的网址重新请求该资源。

从地址栏显示来说: forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址。redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.从数据共享来说: forward:转发页面和转发到的页面可以共享request里面的数据. redirect:不能共享数据.从运用地方来说: forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等从效率来说: forward:高. redirect:低.

5.4 HTTPS

Http不足

通信内容使用明文,因此内容可能被窃听 无法验证数据的完整性,报文可能已经被修改 不验证通信方的身份,可能遭遇伪装

HTTPS主要解决的就是这三件事,首先为了保证内容不被窃听,HTTPS协议通信的内容都是加密的,并且加入了数字签名来保证数据的完整性,另外,为了确保最开始客户端与服务端建立安全连接,服务端需要去官方的正规的证书颁发机构申请证书,然后把自己的公钥放在证书里发给客户端,用证书来保证公钥的来源是真实可信的。

HTTPS就是在HTTP与TCP层中间添加了一个SSL层。因为HTTPS被HTTP多了这层加密的流程,所以HTTPS的速度要比HTTP慢的多。

Https和Http区别

HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。HTTPS使用数字签名来保证数据的完整性,而HTTP不能保证HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。HTTP 安全性没有 HTTPS高,但是 HTTPS 比HTTP耗费更多服务器资源。

HTTPS发起请求的流程

SSL的加密过程是RSA与AES混合进行的。简单概括一下,就是通过RSA加密方式来交换AES加解密的密钥,然后使用AES加密的方式来传输报文。

客户端向服务器发起HTTPS的请求,连接到服务器的443端口;服务器将非对称加密的公钥以证书的形式回传到客户端客户端解析证书,验证其合法性,如果有问题,则HTTPS请求无法继续;如果没有问题,则上述公钥是合格的客户端生成一个随机值,这个随机值就是用于对称加密的密钥(client key)客户端会发起HTTPS中的第二个HTTP请求,将服务器端公钥加密后的客户端密钥发送给服务器服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后的明文就是客户端密钥,然后用客户端密钥对数据进行对称加密服务器用客户端密钥对数据加密,并将密文发送给客户端客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据

数字签名

基于散列函数验证信息的完整性。

常见的有 MD5、SHA1、SHA256,该类函数特点是函数单向不可逆、对输入非常敏感、输出长度固定,针对数据的任何修改都会改变散列函数的结果,用于防止信息篡改并验证数据的完整性;

客户端如何验证证书合法性

需要权威的第三方机构CA(如沃通CA)去证明服务器身份,CA 负责核实公钥的拥有者的信息,并颁发认证"证书",同时能够为使用者提供证书验证服务,即PKI体系

服务方S向第三方机构CA提交公钥**(注意不用提交私钥!!)**、组织信息、个人信息(域名)等信息并申请认证CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等如信息审核通过,CA会向申请者签发认证文件-证书。客户端 C 向服务器 S 发出请求时,S 返回证书文件客户端 C读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法客户端然后验证证书相关的域名信息、有效时间等信息;客户端会内置信任CA的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA的证书,证书也会被判定非法。

简述SSL与TLS

SSL:(Secure Socket Layer) 安全套接层,于 1994 年由网景公司设计,并于 1995 年发布了3.0 版本TLS:(Transport Layer Security)传输层安全性协议,是 IETF 在 SSL3.0 的基础上设计的协议

上述两种技术的出现是为了解决HTTP中存在的安全性问题。例如,使用明文通信,内容被窃听;不验证身份,身份可伪装;无法验证报文完整性,容易被篡改。HTTPS=HTTP+TLS,并使用TSL作为安全保障,对传输内容加密并做身份验证。

简述下CA

证书:全称公钥证书(Public-Key Certificate, PKC),里面保存着归属者的基本信息,以及证书过期时间、归属者的公钥,并由认证机构(Certification Authority, CA)施加数字签名,表明,某个认证机构认定该公钥的确属于此人。数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。

服务器的运营人员向CA提出公开密钥的申请,CA在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该开密钥放入公开密钥证书后绑定在一起。进行HTTPS通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。

对称加密 非对称加密

对称加密,指的就是加、解密使用的同是一串密钥(DES,AES) 非对称加密,指的是加、解密使用不同的密钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。反之,私钥加密的信息,只有公钥才能解密(RSA) 对称加密效率高,但没有非对称加密安全

如果都用非对称加密有什么缺点

虽然非对称加密很安全,但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。

非对称加密原理

https://blog.csdn.net/jijianshuai/article/details/80582187

公钥加密 - 私钥解密流程图

私钥加密-公钥解密流程图

对称加密原理

AES算法:对明文矩阵进行多轮的轮密相加、字节代换、行位移、列混合等…

Https中的攻击

中间人攻击原理

针对SSL的中间人攻击方式主要有两类,分别是SSL劫持攻击和SSL剥离攻击

SSL劫持攻击

SSL劫持攻击即SSL证书欺骗攻击,攻击者为了获得HTTPS传输的明文数据,需要先将自己接入到客户端和目标网站之间;在传输过程中伪造服务器的证书,将服务器的公钥替换成自己的公钥,这样,中间人就可以得到明文传输带Key1、Key2和Pre-Master-Key,从而窃取客户端和服务端的通信数据;

但是对于客户端来说,如果中间人伪造了证书,在校验证书过程中会提示证书错误,由用户选择继续操作还是返回,由于大多数用户的安全意识不强,会选择继续操作,此时,中间人就可以获取浏览器和服务器之间的通信数据

SSL剥离攻击

这种攻击方式也需要将攻击者设置为中间人,之后见HTTPS范文替换为HTTP返回给浏览器,而中间人和服务器之间仍然保持HTTPS服务器。由于HTTP是明文传输的,所以中间人可以获取客户端和服务器传输数据

Https的抓包分析

https://www.jianshu.com/p/852f910d55e2

为什么https被抓包工具抓到的也是明文?

抓包工具伪造了自签名证书之后可以成功抓包,并且抓到的是明文。

https抓包的原理就是抓包程序将服务器返回的证书截获 ,然后给客户端返回一个它自己的证书;客户端发送的数据抓包程序用自己的证书解密,然后再用截获的证书加密,再发给服务器 所以你在能看到明文。密文是针对https两端以外其他路径而言,抓包程序作为https链接的两端,当然可以看到明文 。

加密层位于http层(应用层)和tcp层(传输层)之间, 所以抓到的http层的数据并没有加密。 同理, 在后台接收端, 经历解密后, 到达http层的数据也是明文。 要注意, https不是对http报文进行加密, 而是对业务数据进行加密, 然后用http传输。所以需要在客户端对密码进行MD5加密处理才行。

5.5 SSH

ssh为什么要放公钥到服务器

ssh 需要进行身份验证。一般都是用非对称的秘钥,公钥的作用是证明提供个密文是不是对应的私钥。当你用私钥登录的时候,服务器就可以用公钥验证你的身份,并且给你预设的权限。

ssh端口映射

ssh xxx@xxx.xxx -L 8023:RemoteIP:23

-L 将本地的某个端口映射到远程主机的某个端口上,上例中就是将本地的8023端口映射到远程主机的23号端口上,这样就可以直接telnet本机的8023端口来访问远程主机了。但是需要说明的是RemoteIP可以是127.0.0.1,此时127.0.0.1指的是远程计算机,而非本机地址。

-R 则正好与-L相反,它将远程主机的某个端口映射到本地的某个端口上,例如:

ssh xxx@xxx.xxx -R 8023:LocalIP:23

上例将远程主机的8023端口映射到本机的23号端口,这样远程主机就可以telnet 自己的8023端口来访问本地主机了。

telnet 相关

综合面试题

在浏览器中输入url地址->显示主页的过程中发生了什么

1、DNS解析

建立TCP连接

2、http协议生成请求报文

3、TCP协议将请求报文分割成报文段,进行可靠连接传输 4、IP协议进行分组转发 (发送HTTP请求) 5、TCP协议重组请求报文,服务器处理请求 6、Http协议对请求进行处理,服务器返回HTTP报文 7、浏览器解析渲染页面

8、释放连接

路由器和交换机的区别

工作层次不同:交换机工作在OSI开放式系统互联模型的数据链路层,也就是第二层,而路由器则工作在OSI模型的网络层,就是第三层。数据的转发对象不同: 交换机是根据MAC地址转发数据帧,而路由器则是根据IP地址来转发IP数据报/分组。分工:交换机主要是用于组建局域网,而路由器则是负责让主机连接外网。

IP地址与MAC地址的区别

IP地址是指互联网协议地址(Internet Protocol Address)IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异MAC 地址又称为物理地址、硬件地址,用来定义网络设备的位置。网卡的物理地址通常是由网卡生产厂家写入网卡的,具有全球唯一性。MAC地址用于在网络中唯一标示一个网卡,一台电脑会有一或多个网卡,每个网卡都需要有一个唯一的MAC地址。

如何设计API的安全性

Token授权机制、时间戳超时机制、签名机制、拒绝重复调用

HTTP攻击有哪些

跨站脚本攻击(XSS)、Dos攻击、SQL注入攻击、OS命令注入攻击、HTTP头部攻击、目录攻击、开放重定向攻击

HTTP和WebSocket的联系和区别,什么情况下用WebSocket

答:HTTP1.x是半双工通信,客户端请求服务器响应,是无状态的,如果要实现实时通讯需要长轮询或者长连接的方式,这两种方式带来资源浪费。WebSocket是HTML5以后基于TCP协议应用层的一种全双工实时通讯协议。客户端和服务端可以进行信息的相互传递。它是借Http请求产生握手,在Http的头部会包含WebSocket协议的请求,所以握手之后,协议进行一个升级,转成TCP协议进行交流。

WebSocket可以应用于聊天和即时信息

WebSocket通信流程

建立socket通信,包括客户端和服务器端创建套接字(socket方法),服务器端绑定端口(bind方法),建立监听(listen方法),客户端创建连接(connect方法)。TCP三次握手建立连接客户端服务器端收发数据(send方法、recv方法),读写数据(read方法、write方法)。TCP四次挥手关闭连接关闭socket(close方法)

TCP连接唯一性如何保证

对TCP而言在三次握手时的SYN标志会使用上一个ISN值,这个值是使用32位计数器,内由0-4294967295,每一次连接容都会分配到一个ISN值,连接双方对这个值会记录共识,假如这个值不一,就说明了这个连接已超时或无效甚至是被人恶意攻击冒充连接。

子网掩码的最大长度

30位,子网掩码将某个IP地址划分成网络地址和主机地址两部分,在一个网段中,有2个地址是被固定占用的,一个是网段地址,一个是网段内广播地址,其他是主机可用的地址,至少一个,不然就没有意义了。也就是说,被掩码所分的网段至少要包含3个地址。

IPV6地址的基本类型

单播(unicast):单播就是传统的点对点通信。多播(multicast):多播是一点对多点的通信,数据报发送到一组计算机中的每一个。IPV6没有广播的术语,而是将广播看作多播的一个特例。任播(anycast):这是IPV6增加的一种类型。任播的终点是一组计算机,但是数据包只交付给其中一个,通常是距离最近的一个。

高性能短链

短链的好处:

链接变短,在对内容长度有限制的平台发文,可编辑的文字就变多了(微博140字限制)将链接转成二维码的形式分享给他人,如果是长链的话二维码密集难识别,短链就不存在这个问题了链接太长在有些平台上无法自动识别为超链接

短链接链接跳转的原理

可以看到请求后,返回了状态码 302(重定向)与 location 值为长链的响应,然后浏览器会再请求这个长链以得到最终的响应。

**采用302——临时重定向的好处:**每次去请求短链都会去请求短网址服务器(除非响应中用 Cache-Control 或 Expired 暗示浏览器缓存),这样就便于 server 统计点击数,所以虽然用 302 会给 server 增加一点压力,但在数据异常重要的今天,这点代码是值得的,所以推荐使用 302!

短链生成的几种方法

1、哈希算法

MD5,SHA 等算法是加密就意味着性能上会有损失,我们其实不关心反向解密的难度,反而更关心的是哈希的运算速度和冲突概率。

Google 出品的 MurmurHash 算法,MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。与其它流行的哈希函数相比,对于规律性较强的 key,MurmurHash 的随机分布特征表现更良好。非加密意味着着相比 MD5,SHA 这些函数它的性能肯定更高(实际上性能是 MD5 等加密算法的十倍以上),也正是由于它的这些优点,所以虽然它出现于 2008,但目前已经广泛应用到 Redis、MemCache、Cassandra、HBase、Lucene 等众多著名的软件中。

如何解决哈希冲突的问题?

将长链(lurl)经过 MurmurHash 后得到短链。再根据短链去 short_url_map 表中查找看是否存在相关记录,如果不存在,将长链与短链对应关系插入数据库中,存储。如果存在,说明已经有相关记录了,此时在长串上拼接一个自定义好的字段,比如「DUPLICATE」,然后再对接接的字段串「lurl + DUPLICATE」做第一步操作,如果最后还是重复呢,再拼一个字段串啊,只要到时根据短链取出长链的时候把这些自定义好的字符串移除即是原来的长链。

2、自增序列算法

维护一个 ID 自增生成器,比如 1,2,3 这样的整数递增 ID,当收到一个长链转短链的请求时,ID 生成器为其分配一个 ID,再将其转化为 62 进制,拼接到短链域名后面就得到了最终的短网址。

生成ID的方法:1、redis(需要做持久化) 2、雪花算法 3、MySQL 自增主键

常见web攻击有哪些?

XSS

XSS攻击:跨站脚本攻击(Cross-Site Scripting),将恶意代码植入到提供给其它用户使用的页面中。目标是为了盗取存储在客户端的cookie或者其他网站用于识别客户端身份的敏感信息。一旦获取到合法用户的信息后,攻击者甚至可以假冒合法用户与网站进行交互。

**例子:**我写了一个网站,然后攻击者在上面发布了一个文章,内容是这样的 ,如果我没有对他的内容进行处理,直接存储到数据库,那么下一次当其他用户访问他的这篇文章的时候,服务器从数据库读取后然后响应给客户端,浏览器执行了这段脚本,就会将cookie展现出来,这就是典型的存储型XSS。

如何预防XSS

坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的XSS攻击。

过滤特殊字符 避免XSS的方法之一主要是将用户所提供的内容进行过滤(如上面的script标签)。使用HTTP头指定类型 w.Header().Set("Content-Type","text/javascript") 这样就可以让浏览器解析javascript代码,而不会是html输出。

SQL注入

攻击者成功的向服务器提交恶意的SQL查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码。

举例:' OR '1'='1,当我们输如用户名 admin ,然后密码输如' OR '1'=1='1的时候,我们在查询用户名和密码是否正确的时候,本来要执行的是SELECT * FROM user WHERE username='' and password='',经过参数拼接后,会执行 SQL语句 SELECT * FROM user WHERE username='' and password='' OR '1'='1',这个时候1=1是成立,自然就跳过验证了。

如何预防SQL注入

#{}可以防止sql注入 ${}

使用预编译语句(PreparedStatement),这样的话即使我们使用 SQL语句伪造成参数,到了服务端的时候,这个伪造 SQL语句的参数也只是简单的字符,并不能起到攻击的作用。

```java

DDOS

DDOS:分布式拒绝服务攻击(Distributed Denial of Service),简单说就是发送大量请求是使服务器瘫痪。

在技术角度上,DDoS攻击可以针对网络通讯协议的各层,手段大致有:TCP类的SYN Flood、ACK Flood,UDP类的Fraggle、Trinoo,DNS Query Flood,ICMP Flood,Slowloris类等等。一般会根据攻击目标的情况,针对性的把技术手法混合,以达到最低的成本最难防御的目的,并且可以进行合理的节奏控制,以及隐藏保护攻击资源。

SYN攻击

SYN攻击指的是,攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。

常用端口

FTP:21

Tomcat:8080

NGINX:80

dns:53

https:443

mysql:3306

neo4j:7687

负载均衡

将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。用户直接访问负载均衡器,再由负载均衡器将请求转发给后端服务器

负载均衡算法

负载均衡算法决定了后端的哪些健康服务器会被选中。几个常用的算法:

**Round Robin(轮询):**为第一个请求选择列表中的第一个服务器,然后按顺序向下移动列表直到结尾,然后循环。**Least Connections(最小连接):**优先选择连接数最少的服务器,在普遍会话较长的情况下推荐使用。**Source:**根据请求源的 IP 的散列(hash)来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。

代理服务器

代理服务器的概念

个人网络和Internet服务商之间的中间代理机构,它负责转发合法的网络信息,对转发进行控制和登记,作为连接Internet(广域网)与Intranet(局域网)的桥梁。

代理服务器和网关有什么区别?

网关bai就是你要访问另一个网络时,首先需要访问的网络节点。比喻你有两个不同的内网,在A网中要访问B网,则首先需要访问网关,由它那里路由转发。所以,代理服务器可以说是一个网关,但网关并不一定是代理服务器。里写自定义目录标题)

推荐阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。