计算机网络基础知识总结
计算机网络基础知识总结
TCP/IP协议族
现代Internet主要使用的协议族是TCP/IP协议族,它是一个四层协议系统,自顶向下的话是应用层,传输层,网络层,数据链路层。每一层都有自己需要完成的功能,包含着若干协议的实现,上层协议的使用依赖下层协议提供的服务。
图来自Linux高性能服务器编程
应用层
应用层复制处理应用程序的逻辑,应用层是在用户空间实现的,而传输层,网络层和数据链路层都是在内核空间完成的。
应用层协议比较多,常见的有telnet、OSPF、DNS等协议。
telnet协议是一种远程登录协议,可以让我们能够在本地完成远程任务。
OSPF协议一种动态路由更新协议,用户路由器之间的通信,可以告知对方各自的路由信息。
DNS协议提供机器域名到IP地址的转换。
应用层协议不一定都需要传输层提供的服务,可以直接使用网络层提供的服务(OSPF)。
传输层
传输层为两台主机上的应用程序提供端对端的通信,传输层只关心通信的起始端和目的端,而不关注数据报的中间过程。
传输层主要是为应用程序封装了一条端到端的逻辑通信链路,负责数据的收发,链路的超时重连等。
传输层协议主要有三个:TCP协议,UDP协议,SCTP协议。
TCP协议主要是为应用层提供可靠的,面向连接的和基于流的服务,TCP协议使用超时重传,数据包检验、应答机制、对失序数据报重排序和流量控制来确保数据包被正确的发送至目的端。使用TCP协议进行通信必须先建立连接,并且在内核中为该连接维持一些数据结构(连接的状态,读写缓冲区和定时器等)。当通信结束之后,服务器和客户端都必须关闭连接和释放数据资源。TCP是基于流的,没有边界限制(会存在半包,粘包问题),它会从通信的一端流入另一端,发送端可以逐个字节的向数据流写入数据,接收端也可以逐个字节读取数据。
UDP协议是无连接,不可靠,基于数据报的服务,它无法保证接收端可以正确接收到发送段发送的数据,如果数据中途丢失,或者发送错误而被丢弃,UDP协议只是简单地通知应用程序发送失败,需要用户自己处理数据确认,超时重传的逻辑。
UDP是基于数据报的服务,每一个UDP数据报都有一个长度,接收端可以根据该长度将内容一次性读取出来。
SCTP协议是在因特网上传输电话信号而设计的。
网络层
网络层主要是实现数据包的选路和转发。广域网(WAN)一般使用路由器来连接分散的主机或者局域网(LAN)。
一般情况下,通信的两台主机都不是直接相连的,而是通过多个中间节点进行连接通信,网络层就是选择这些中间节点,确定两台主机之间的通信路径,对上层协议隐藏网络拓扑连接的细节。
网络层主要使用的协议是IP/ICMP协议,IP协议根据数据包的IP地址来决定如何传递它,如果数据报不能直接发送给目标主机,那么IP协议就会寻找一个合适的下一跳路由器,并将数据报交付给路由器进行转发,多次重复之后到达目标主机,或者发送失败而被丢弃。ICMP主要使用来检查网络连接(使用同一层网络层提供的服务)
数据链路层
数据链路层实现了网卡接口的网络驱动程序,来处理数据在物理介质上(不同的物理网络具有不同的电气特性)的传输。
数据链路层主要使用的两个协议是ARP(地址解析协议)和RARP(逆地址解析协议),它们实现了IP地址和机器物理地址(Mac地址)的相互转换。
网络层通过IP地址寻址一台机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须要将目标机器的IP地址转化为物理地址,才能使用数据链路层的服务。
封装和分用
封装
上层协议想要使用下层协议提供的服务的话,需要在自身数据的基础之上添加下层协议的头部进行封装,通过协议栈自顶向下的传递,就可以将数据发送到物理网络上。
- 通过TCP封装的数据称为TCP报文段,TCP协议为通信双方维持一个连接,并在内核中存储相关的数据,TCP的头部信息和TCP内核缓冲区(发送缓冲区和接收缓冲区)数据构成了TCP报文段。当发送端使用send/write函数向TCP连接写入数据时,内核中的TCP模块首先将这些数据复制到与该连接对应的TCP内核发送缓冲区中(需要保存数据副本),然后TCP模块调用IP模块提供的服务。
- 使用UDP封装的数据称为UDP数据报,与TCP类似,不过由于UDP是不可靠的,不需要在应用层保存数据副本,当一个UDP数据报成功发送之后,UDP内核模块的数据就会被丢弃,如果数据没有被接收端成功接收,而且想要重新发送这个数据报,应用程序需要重新从用户空间将该数据报拷贝到UDP内核发送缓冲区。
- 使用IP封装的数据称为IP数据报,IP数据报包括头部信息和数据部分(TCP报文端,UDP数据报,ICMP报文)
- 而经过数据链路层封装的数据称为帧,传输媒介不同,帧的类型也不同,在以太网传输的是以太网帧,令牌环网络上传输的是令牌环帧。帧的最大传输单元(MTU),帧最多能携带多少上层协议数据会受到网络类型的限制。
分用
当帧到达目的主机之后,会沿着协议栈自底向上依次传递。每层协议会依次处理帧中本层负责的头部数据,获取所需的信息,并最终将处理后的帧交给目标应用数据。
分用是根据头部信息中的类型字段实现的。
由于IP\ARP协议都是使用帧来传输数据的,帧的头部需要提供一个字段来进行区分,以太网帧使用2字节的类型字段来标志上层协议,如果主机接收到的以太网帧的类型字段的值为0x800,则帧的数据报部分为IP数据报,以太网启动程序就会将其交付给IP模块;如果类型字段为0x806,那帧的数据部分为ARP请求或应答报文,以太网驱动程序将帧交付给ARP模块;若类型字段的值为0x835,则帧的数据部分为RARP请求或应答报文,以太网驱动就会将其交给ARP模块处理;如果类型字段为0x835,则帧的数据报部分为RARP请求或应答报文,以太网驱动程序就会将其交给RARP模块。
ICMP/TCP/UDP协议都使用了IP协议,所以IP数据报的头部采用16位的协议字段来进行区分。
- TCP/UDP则是在头部使用了16位的端口号字段来区分上层应用程序,DNS端口号为53,http端口号为80,我们可以在/etc/services文件找到知名应用层协议使用的端口号。
- 最后分用完成之后,就将封装之前的数据送至给目标服务。
IP/ARP/RARP协议
ARP协议
ARP协议能实现任意网络层地址到任务物理地址的转换,原理主要是每个安装有TCP/IP协议的主机或者路由器,都有一个ARP缓存表,表里面的IP地址和Mac地址是一一对应的,当主机A向主机B发送数据的时候,主机A首先会检查自己的ARP缓存表,查找是否有目标主机B的IP地址,如果找到了的话,就会将对应的mac地址写回帧中返回就可以了;否则没有找到的话,主机A就在其所在的网络发送一个广播(ARP请求),请求的目标mac地址为‘FF.FF.FF.FF.FF.FF’,表示在同一网段的所有主机发起询问,只有目标主机才能接收这个帧,响应ARP询问,其他主机不响应,然后主机A就知道了主机B的mac地址,可以发送数据了,同时主机A会更新ARP缓存表,当下次向主机B发起请求的时候,可以直接从缓存表中获取,不需要发起广播。
ARP请求/应答报文
硬件地址类型:定义物理地址的类型,以太网(0x0001)。
协议地址类型:定义要映射的协议地址类型,IP地址(0x8000)、IPv6(0x86DD)。
硬件地址长度:硬件地址的字节长度,一般为6。
协议地址长度:协议地址的字节长度,一般为4。
操作码:1为ARP请求,2为ARP应答,RARP请求为3,RARP应答为4。
源硬件地址:n个字节,n由硬件地址长度得到,发送方MAC地址。
源协议地址:m个字节,m由协议地址长度得到,发送方IP地址。
目标硬件地址:n个字节,n由硬件地址长度得到,目标MAC地址。
目标协议地址:m个字节,m由协议地址长度得到,目标IP地址。
发送端会填充除了目的硬件地址的3个地址,然后构建ARP请求并发送之,当目标主机接发现该请求的IP地址是自己之后,会填充自己的以太网地址进去,然后交换目标地址和源地址,修改操作码为2,构建ARP应答返回。
ARP请求/应答报文长度为28字节,然后加上以太网帧的首部14字节和尾部CRC字节,即一个ARP请求/应答的以太网帧长度为46字节。
RARP协议
RARP原理主要是发送主机会发送一个RARP广播,在广播包中,它会填充自己的mac地址并请求任何接收该请求的RARP服务器分配一个IP地址,在主机所在网络的RARP服务器接收到该请求后,会检查其RARP列表有没有该mac地址对应的IP地址,如果有的话,就会构建一个RARP响应包填充得到的IP地址返回给原主机,否则不存在的话,RARP服务器不会做出响应;当原主机接收到从RARP服务器返回的响应消息之后,就可以得到要发送主机的IP地址,就可以进行通信了,否则一直没有接收到响应的话,表示初始化失败。
IP协议
IP协议是TCP/IP协议族的主要协议,它为上层协议提供了无状态、无连接、不可靠的服务。
- 无状态
无状态是指在IP通信双方不会同步传输数据的状态信息,即每一个IP数据报的发送、传输和接收都是相互独立的,没有上下文关系,自身是无法处理重复乱序的数据报的,对于IP模块来说,只要接收到了一个完成的IP数据报,就会将其提交给上层协议,不会进行排序的。IP数据报头部提供的标志字段只能用来唯一的标志一个IP数据报,是用来处理IP分片和重组的,不能用来指示接收顺序。不过由于不需要去维护接收发送双方的状态,可以简单高效的传输数据。 - 无连接
无连接是指IP通信的双方都不会长时间维持对方的任何信息,这需要我们每次发送数据的时候,都需要指定对方的IP地址。 - 不可靠
不可靠是指IP协议并不能保证发送端发出的数据能够准确地发送到接收端,它只能保证尽最大努力去发送,一旦发送端的IP模块检测到IP数据报发送失败,就只是通知上层协议发送失败,而不会重传数据报。
IP头部信息
- 4位版本号指定IP协议的版本,对于IPv4,即是4
- 4位头部长度,标志该IP头部有多少个bit字(1字4字节),4位最大值为15,所以IP头部最长是60字节.
- 7位DSCP包括一个3位的优先权字段,4位的TOS字段,4位的TOS字段表示最小延时、最大吞吐量、最高可靠性和最小费用,最多有一个标志位能设置为1.
- 1位保留字段,必须置0
- 16位总长度是指整个IP数据报的长度,以字节为单位,也就是说IP数据报的最大长度为65534字节,但是由于MTU的限制,长度超过MTU的数据报都要分片传输。
- 16位标志符标志主机发送的每一个数据报,其初始值是由系统随机生成的:每发送一个数据报,其值就会加1,该值会在数据报分片的时候复制到每一个分片中,即同一个数据报的所有分片的标识值都会相同。
- 3位标志字段,第一位保留,第二位表示禁止分片,如果设置了禁止分片的话,IP模块就不会对数据报进行分片,如果IP数据报的长度超过了MTU,那么IP模块会丢弃该数据报并返回一个ICMP差错报文,第三标志位表示更多分片,除了数据报的最后一个分片之外,其他分片都要设置为1.
- 13位分片偏移是指分片相对于原始IP数据报开始处的偏移,实际的偏移值是该值左移3位后得到的,即除了最后一个IP分片之外,每一个IP分片的数据部分的长度必须是8的整数倍。
- 8位存活时间,是指数据报到达目的地之前允许经过的路由器跳数,TTL值被发送端设置(常见为64),数据报在转发过程中每经过一个路由,该值就被路由器减1,当TTL值减为0时,路由器将丢弃数据报,并向源端发送一个ICMP差错报文,TTL可以防止数据报陷入路由循环。
- 8位协议可以用来区分上层协议,ICMP为1,TCP为6,UDP为17,详细的可以在/etc/protocols文件中查看。
- 16位头部检验和,由发送端填充,接收端对其使用CRC算法对IP数据报头部进行检验是否发生损坏。
- 32位的源IP地址和目标IP地址,用来标志数据报的发送端和接收端。
- 选项字段是可变长的可选信息,最多包含40字节,可用的IP选项有:
- 记录路由 告诉数据报途径的所有路由器将自己的IP地址填入IP头部
- 时间戳 告诉每个路由器都将数据报被转发的时间填入到IP头部
- 松散源路由选择 指定一个路由器IP地址列表,数据报发送过程必须经过其中所有的路由器
- 严格源路由选择 数据报只能经过被指定的路由器
IP数据包的分片、路由和转发
分片和组装
当IP数据报的长度超过帧的MTU时候,它就会被分片传输,分片可能发生在可能在传输过程中被多次分片,但只有目标机器上,分片才会被内核的IP模块组装。
IP数据报通过三个字段给IP的分片和重组提供信息:数据报标志,标志和片偏移。一个IP数据报的每个分片有自己的IP头部,他们具有相同的标志值,但是具有不同的片偏移,并且除了最后一个分片之外,都设置MF标志,此外,每个分片的IP头部的总长度字段都将设置为该分片的长度,分片偏移量会设置为合适的值和首部检验和会重新计算。
当接收端发现接收的报文更多分片标志位或者分片偏移量不为0的时候,它就会将其数据和分片偏移量和更多分片标志保存下来,直到收到更多分片标志未被设置的报文,就可以知道原始数据报的总长,一旦收集齐所有分片报文,就可以将他们组装起来交给上层协议。
路由
IP协议还有核心点就是路由,即决定发送数据报到目的机器的路径。
当IP模块接收到来自数据链路层的IP数据报时,他会对该数据报的头部作CRC检验,检验成功之后就根据头部信息进行分析。
如果IP数据报的头部设置了源站选路选项(松散源路由选择或者严格源路由选择),则调用IP模块调用数据报转发子模块来处理该数据报,或者该数据报头部中的目标IP地址是本机的某个IP地址,或者是广播地址,也就是说该数据报是发送给本机的,那么IP模块就会根据数据报头部中协议字段来决定将其派发给哪个上层协议,否则IP数据报发现这个数据包不是发送给本机的,也会调用数据报转发子模块来处理数据报。
数据报IP转发子模块首先会检查系统是否允许转发,如果不允许的话,IP模块就会将数据报丢弃,如果允许的话,数据报转发子模块会对数据报进行操作,然后将其交给IP数据报输出子模块。
计算下一跳子模块通过路由表决定IP数据报会发送至哪个下一跳路由,以及经过哪个网卡来发送,它根据数据报的目标IP地址分类,同一类型的IP数据报会发我能够相同的下一跳路由器。
IP输出队列存放的是所有等待发送的IP数据报,除了需要转发的IP数据报和封装了本机上层数据(ICMP报文,TCP报文段和UDP数据报)的IP数据报。
我们可以通过route命令来查看路由表
- Destination表示目标网络或者主机
- Gateway 网关地址,*表示目标和本机在同一个网络
- Genmask 网络掩码
- Flags 路由项标志
- U 该路由项是活动的
- H 该路由项的目标是一台主机
- G 该路由项的目标是网关
- D 该路由项是重定向生成的
- M 该路由向被重定向修改过。
- Metric 路由距离,即可到达制定能够网络所需的中转数
- Ref 路由项被引用的次数
- Use 该路由项被使用的次数
- Iface 该路由项对应的输出网卡接口
路由表的第一项是default,表示默认路由,flags为G,表示下一条目标是网关,地址是192.168.1.1,另一个路由项的目标项是192.168.1.0表示本地局域网,该路由项的网关地址为*,表示数据报不需要路由中转,可以直接发送到目标机器。
IP的路由机制:首先查找路由表中有没有与目的IP地址完全匹配的主机IP地址,如果找到的话,就使用该路由项,否则的话查找路由表中和数据报中的目的IP地址具有相同的网络ID的网络IP地址,如果找到则使用该路由项,否则就选择默认路由项,一般表示就是下一跳路由是网关。
路由的更新可以是通过route或者工具手动修改路由表,即静态路由更新,否则可以通过BGP、RIP和OSPF等协议动态更新路由
转发
对于允许IP数据报转发的系统(主机或者路由器),数据报转发子模块将对期望转发的数据报执行以下操作,首先检查数据报头部的TTL值,如果是0,则丢弃该数据报,否则话就查看数据报头部是否设置了严格源路由选择选项,设置了的话就检查数据报的目标IP地址是否是本机的某个IP地址,如果不是,则发送一个ICMP源站选择失败报文给发送端。如果有可能的话,给源端发送一个ICMP的重定向报文,告诉其一个更合理下一跳路由器。然后将TTL值减1,处理IP头部选项,有可能执行IP分片操作。
TCP/UDP协议
TCP
TCP连接是面向连接、字节流和可靠传输的传输层协议。
使用TCP协议进行通信的双方必须先建立连接,然后才能开始数据的读写,双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输,TCP连接是全双工的,即双方的数据读写可以在一个连接进行,完成数据交换之后,通信双方都必须断开连接来释放系统资源。
TCP连接是一对一,不可以用来多播或者广播。
TCP头部信息
16位源端口/目的端口,告诉主机该报文段是来自哪里和要传给上层协议或者应用程序端口的。一般进行TCP通信的时候,客户端通常使用系统自动选择的临时端口号,而服务器使用知名服务端口号。
32位序列号码 一次TCP通信过程中某一个传输方向上的字节流的每一个字节的编号。在进行主机A和主机B建立TCP通信的时候,主机A发送给主机B的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(初始序号值),在该传输方向上的后续TCP报文段中序号值被系统设置为ISN加上该报文端所携带数据的第一个字节在整个字节流中的偏移。
32位确认序号 用作对另一方发送来的TCP报文段的响应,其值是收到的TCP报文段的序号值加1.
4位头部长度,标志该TCP头部有多少个32bit字(4字节),TCP头部最长为60字节。
6位标志位
- URG标志,表示紧急指针是否有效
- ACK标志,表示确认号是否有效,带有ACK标志的报文段称为确认报文段。
- PSH标志 提示接收端应用程序该立即从TCP接收缓冲区中读取数据,为接收后的数据提供空间。
- RST标志 表示要求对方重新建立连接
- SYN标志 表示请求建立连接
- FIN标志 表示通知对方本端要关闭连接了。
- 16位窗口大小,TCP流量控制的一个手段,窗口是指接收通告窗口,它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,让对方控制发送数据的速度。
- 16位校验和,由发送端填充,接收端会对TCP报文段执行CRC算法检验TCP报文段在传输过程中是否损坏。(检验TCP头部和数据部分)
- 16位紧急指针 一个正的偏移量,它与序列字段的值相加表示最后一个紧急数据的下一字节的序号。
TCP连接的建立和关闭
TCP连接是通过三次握手进行初始化的,三次握手主要是为了同步连接双方的序列号和确认号并交换TCP窗口大小信息。
- 首先主动连接的客户端会向服务器发送一个SYN置位的TCP报文,其中包含连接的初始序列号x和一个窗口大小(表示客户端上用来存储从服务器发送来的传入段的缓冲区的大小)。
- 然后服务器接收到客户端发送过来的SYN报文后,会向客户端发送一个SYN和ACK都置位的TCP报文,报文包含它选择的初始序列号y 、对客户端的序列号的确认x+1和一个窗口大小(表示服务器上用来存储从客户端发送来的传入段的缓冲区的大小)。
- 当客户端接收到服务器端返回的SYN+ACK 报文后,会向服务器端返回一个确认号y+1和序号x+1的ACK 报文,TCP连接成功建立。
由于TCP连接是全双工的,因此,每一传输方向都需要单独的进行关闭,即当一方完成数据传输任务之后,需要发送一个FIN来终止这个方向的连接。但是要记住,接收fin报文只是说明在这个方向上不再接收数据,但是在这个方向上仍可以发送数据,直到这一方向也发送FIN报文,即四次挥手关闭连接。
首先执行关闭的一方执行主动关闭,而另一方则是被动关闭(也有存在双方同时关闭的可能)
- 第一次挥手:客户端发送一个FIN报文,用来关闭客户端到服务端的数据传送,然后客户端进入FIN_WAIT_1 状态。
- 第二次挥手:当服务端收到FIN 后,发送一个ACK报文给客户端,确认序号为收到序号+1 (与SYN相同,一个FIN报文占用一个序号),然后服务端进入CLOSE_WAIT 状态。
- 第三次挥手:服务端发送一个FIN报文,用来关闭服务端到客户端的数据传送,然后服务端进入LAST_ACK状态。
第四次挥手:客户端收到FIN报文后,客户端进入TIME_WAIT状态,接着发送一个ACK给服务端,确认序号为收到序号+1 ,服务端 进入CLOSED状态,完成四次挥手。
TCP状态转移过程
time_wait
我这里主要要分析的是time_wait状态,其余状态有空再补(立flag,逃
time_wait状态在客户端接收到服务器的结束报文段之后没有直接进入close状态,而是转移到time_wait状态,在这个状态,客户端连接需要等待一段长为2MSL(报文段最大生存时间)的时间(默认为2min),才能完全关闭。
TIME_WAIT状态可以可靠的终止TCP连接和保证迟来的TCP报文段有足够的时间被识别并丢弃。
如果客户端向服务器发送的确认终止报文丢失的话,那么服务器将会重发该结束报文段,因此客户端需要停留在某个状态来处理重复收到的结束报文段,用来可靠的终止TCP连接,否则客户端将会以复位报文来回应服务器。
由于一个TCP端口不能被同时打开多次,当一个TCP连接处于time_wait状态时,我们无法立即使用该连接占用着的端口简历一个新连接,否则的话,应用程序可以立即建立一个和刚关闭的连接相似的连接(具有相同的ip地址和端口号),这样的话,新的连接可能会接收到之前连接即迟到的报文段,然而这是不合理的,所以需要存在的原因。
然而为什么要需要2MSL长的时间呢,因为TCP报文段最长生存时间是MSL,保持2MSL长的时间能够保证网络上两个传输方向上还没被接收到的迟到的TCP报文彻底消失。TCP数据流
TCP报文段携带的应用程序数据分为两种:交互数据和成块数据。
交互数据
交互数据只包含很少的字节,使用交互数据的应用程序一般对实时性的要求高.
在交互数据传输中。客户端对服务器返回的数据所发送的确认报文字段都不携带应用程序数据,而服务器给客户端返回的确认报文数据都会包含它所需要的应用程序数据,称为延迟确认,即他不会马上确认上次收到的数据,而是在一段延迟时间之后查看本端是否有数据需要发送,如果有的话,就会和确认报文一起发出。延迟确认可以减少发送TCP报文段的数量。
Nagle算法要求一个TCP连接的通信双方可以在任意时刻都最多只能发送一个未被确认的TCP报文段,在读TCP报文段的确认到达之前不能发送其他TCP报文段,发送方在等待确认的同时收集本端需要发送的微量数据,并在确认到来时以一个TCP报文段将他们全部发出,可以减少网络上微小TCP报文段的数量。成块数据
成块数据通常为TCP报文段允许的最大数据长度,一般对传输效率要求比较高。
滑动窗口协议
TCP数据流控制
超时重传
TCP服务器能够重传超时时间内未收到确认的TCP报文段,为此,TCP模块会为每一个TCP报文段都维护一个重传定时器,该定时器会在TCP报文段第一次被发送时启动,如果在超时时间段内未收到接收方的应答,TCP模块就会重传TCP报文段并重置定时器,而重传策略就是选择下次重传的时间和最多执行多少次重传,而且每次重传超时时间都会倍增。
(可以通过设置linux内核参数/proc/sys/net/ipv4/tcp_retries1,/proc/sys/net/ipv4/tcp_restries2来指定底层ip接管之前TCP最少执行的重传次数,默认为3,以及连接放弃前TCP最多可以执行的重传次数,默认值是15)
超时会导致TCP报文段重传,但是TCP报文段的重传可以发生在超时之前,即快速重传。拥塞控制
拥塞控制是为提供网络的利用率,降低丢包率保证网络资源和每条数据流的公平性。
拥塞控制的最终受控变量是发送端向网络一次连续写入(收到其中第一个数据之前)的数据量,即SWND(发送窗口),由于发送端是以TCP报文段来发送数据,所以SWND主要限制发送端能连续发送的TCP报文段数量,报文段的最大长度(数据部分)称为SMSS(发送者最大段大小),其值一般等于MSS。
发送端需要合理的选择SWND的大小,如果SWND太小,会引起网络延迟,否则太大的话,容易导致网络拥塞。接收方通过接收通告窗口(RWND)和拥塞窗口(CWND)的状态变量来控制发送端的SWND,SWND值是RWND和CWND中的较小者。慢启动和拥塞避免
慢启动是指由于TCP模块开始发送数据不知道网络的实际情况,开始的时候需要进行试探,在TCP连接建立之后,CWND会被设置成初始值,其大小为2-4SMSS,此后发送端每收到接收端的一个确认,其CWND就增加CWND+=min(N,SMSS),N是此次确认中包含的之前未被确认的字节数,这样的话,CWND就以指数形式扩大。
但是慢启动很快就会膨胀,导致网络阻塞,因此TCP拥塞控制定义了一个控制状态变量:慢启动门限(ssthresh),当CWND的大小超过该值时,TCP拥塞控制就会进入拥塞避免阶段。
拥塞避免算法可以让CWND按照线性方式增加.- 不管在一个RTT时间内发送端收到多少个确认,每个RTT时间内按照CWND+=min(N,SMSS)计算新的CWND。
- 每收到一个对新数据的确认报文段通过CWND+=SMSS*SMSS/CWND对CWND进行更新。
以上是TCP如何避免拥塞,但是当拥塞已经发生时,拥塞控制是如何处理的,首先我们需要判断拥塞是否已经发生:传输超时即TCP重传定时器溢出和接收到重复的确认报文。
拥塞控制当发生传输超时的时候,使用慢启动和拥塞避免处理,当接收到重复的确认报文的时候,使用快速重传和快速恢复来处理。
如果发送端检测到拥塞发生是由于传输超时,执行重传的时候会执行以下调整:ssthresh=max(FlightSize/2,2*SMSS),CWMD<=SMSS,FlightSize是指已经发送但未收到确认的字节数,调整之后CWMD将小于SMSS,也小于新的慢启动门限值,一定不小于SMSS的两部,拥塞控制再次进入慢启动阶段。
- 快速重传和快速回复
当发送端接收到重复的确认报文报的时候,拥塞控制算法需要判断当接收到重复的确认报文段的时候,网络是否真的发生了拥塞,或者TCP报文段发送丢失了。首先发送端连续收到了3个重复的确认报文段,那么拥塞就真的是发生了,然后它就会启动快速重传和快速恢复来处理拥塞。首先当收到第三个重复的确认报文段的时候,会ssthresh=max(FlightSize/2,2SMSS)重新计算ssthresh,然后立即重传丢失的报文段,然后设置CWND,CWND=ssthresh+3SMSS;每次接收到一个重复的确认时,设置CWND=CWND+SMSS,此时发送端可以发送新的TCP报文段;若接收到新数据的确认时,会设置CWND=ssthresh,当快速重传和快速恢复完成后,拥塞控制就恢复到拥塞避免阶段。
UDP
UDP是一个不可靠的传输层协议,一旦把传给网络层的数据发送出去,就不会保留数据备份,UDP仅在IP数据报的头部加入了复用和数据校验。
UDP首部字段由4个部分组成,其中两个是可选的。
16位的來源端口和目的端口用来标记发送和接受的应用进程。
由于UDP协议不需要应答,即來源端口是可选的,如果來源端口不用,那么置为零。
在目的端口后面的是长度固定的以字节为单位的长度域,用来指定UDP数据报包括数据部分的长度,长度最小值为8位。
首部剩下的16位是用来对首部和数据部分做校验和的。
DHCP协议
DHCP是一个局域网的网络协议,主要是用来内部网络或者网络服务供应商自动分配IP地址给用户和网络管理员用来作为对所有主机作中央处理的手段。
当我们想访问网络的时候,需要我们去设置本地的IP地址、子网掩码、网关的IP地址,DNS服务器的IP地址。
我们可以自己手动设置,那么计算机开机的时候,都会分配到同样的IP地址,称为静态IP地址上网。
不过一般情况都是使用DHCP协议进行动态IP地址上网,即计算机开机后,都会自动分配到一个IP地址,不需要认为设置。
DHCP协议规定在每一个子网络里面本网络的所有IP地址,称为DHCP服务器,新的计算机如果想加入网络的话,就需要向DHCP服务器发送一个DHCP数据报,申请IP地址和相关的网络参数。
但是如果两台计算机在同一个子网络中,就必须知道对方的MAC地址和IP地址才能进行通信,刚加入进来的计算机并不知道这两个地址,它首先以太网头部设置源mac地址(本机的mac地址)和接收方的mac地址(由于不知道DHCP服务器的mac地址,因此填入的是广播地址:FF-FF-FF-FF-FF-FF),在网络层IP数据报头部设置发出方和接收方的IP地址,发送方的IP地址设置为0.0.0.0,接收方的IP地址为255.255.255.255,在UDP协议数据报填充发送方的端口和接收方的端口,这里由DHCP协议规定,发出方端口为68,接收方为67端口。
在数据包构造完成之后,通过以太网进行广播发送,在同一个子网络的每台计算机都会接收到这个数据报,由于接收方的mac地址为FF-FF-FF-FF-FF-FF,每台主机都会接收这个数据报,然后分析数据报的IP地址,发现发送方IP地址为0.0.0.0,接收方的IP地址为255.255.255.255,然后DHCP服务器就可以知道数据报是发给它的,其他主机丢弃这个数据报。
然后DHCP服务器读取数据报的内容,分配IP地址,发出一个DHCP响应数据报,以太网头部的mac地址的双方的mac地址,IP数据报的源IP地址是DHCP服务器的IP地址,目的IP地址为255.255.255.255,UDP数据报头部的源端口是67和目标端口为68.
分配给请求端的IP地址和子网络的参数就包含数据部分。
新加入的计算机接收到这个响应包,就可以直到自己的IP地址,子网掩码、网关地址和DNS服务器等参数了。
DNS协议
当我们需要访问互联网的时候,一般是通过域名进行访问,而如果想要对远程服务器进行访问,我们需要是知道服务器的IP地址,DNS为我们提供将域名映射为IP地址的服务,它是一个将域名和IP相互映射的分布式数据库,让我们能够更方便的访问互联网,DNS协议使用知名端口53。
DNS解析分为两种:迭代解析和递归解析,默认为递归解析。
递归解析
递归解析主要是通过本地名称服务器进行查询,如果客户端配置的本地名称服务器不能解析的话,那么接下来的话都会使用本地名称服务器代替DNS客户器进行查询,直到本地名称服务器从权威名称服务器得到结果,然后由本地名称服务器返回结果给DNS客户端。
在递归解析的过程中,是以本地名称服务器为中心,DNS客户端只发出最初的域名查询请求报文,然后就一直处于等待状态,直到本地名称服务器返回最终结果,本地名称服务器作为一个中间代理的作用。
基本流程:
- 首先客户端会向本机配置的本地名称服务器,发出DNS域名查询请求。
- 本地名称服务器接收请求之后,它首先会本地缓存中进行查找,如果直到对应域名的记录项,就直接返回查询结果给客户端;否则没有查询到对应的纪录项的话,本地名称服务器就会发送相同的DNS域名查询请求给根名称服务器。
- 根名称服务器收到DNS查询请求之后,就根据请求中的顶级域名找到对应的顶级域名服务器地址,然后把查询得到的地址返回给本地名称服务器。
- 本地名称服务器根据根名称服务器返回的顶级名称服务器地址,向对应的顶级名称服务器发送DNS域名查询请求。
- 对应的顶级域名服务器在收到DNS查询请求之后,先查询对应的本地缓存,如果有对应请求的DNS域名的记录项,就直接把对应的记录项返回给本地名称服务器,然后由本地名称服务器返回给DNS客户端,否则向本地名称服务器返回DNS查询请求的域名的二级域名所有二级域名服务器地址,然后本地名称服务器继续按照上面的步骤进行向三级、四级名称服务器查询,直到对应的域名服务器所在区域的权威名称服务器返回最终的记录给本地名称服务器,然后再由本地名称服务器返回给DNS客户端,同时本地名称服务器会记录这次查询得到的记录项。
如果在以上流程中,对应的权威名服务器找不到对应的记录项,就会向本地名称服务器返回一条查询失败的DNS应答报文(如果该权威名称服务器配置了其他名称服务器转发器,就会向转发器指定的名称服务器查找),最终也会返回给DNS客户端。如在果DNS客户端上配置了多个DNS服务器,就会继续向其它DNS服务器进行查询。
迭代解析
DNS迭代解析的所有查询工作都是由DNS客户端进行。
DNS迭代解析可以在以下两种情况下使用:
- 在查询本地名称服务器的时候,如果客户端的请求报文中没有申请使用递归查询,即DNS查询请求报文头部的RD字段没有设置为1.
- 客户端在DNS请求报文中申请使用递归查询,但是本机设置的本地名称服务器是禁用递归查询的,即在DNS应答报文头部的RA字段置0。
在使用迭代解析的时候,如果配置的主名称服务器不能解析的话,客户端还会继续向所配置的其他名称服务器查询。
基本流程:
- 客户端向本地配置的本地名称服务器发出DNS域名查询请求
- 本地名称服务器接收到请求之后,首先会去查询本地缓存,如果查询到对应的纪录项,就直接把查询的结果返回给DNS客户端,如果本地缓存没有找到的话,就会向DNS客户端返回一条DNS应答报文,报文中会包含参考信息,如根名称服务器的地址。
- DNS客户端接收到本地名称的服务器的应答报文之后,会根据返回的根名称服务器地址,向对应的根名称服务器发出相同的DNS查询请求。
- 根名称服务器接收到DNS查询请求之后,会根据请求域名的顶级域名在DNS数据库查找对应的顶级名称服务器信息,然后返回一条DNS应答报文返回给DNS客户端。
- DNS客户端接收到对应的根名称服务器应答报文之后,找到对应的顶级名称服务器地址信息,向该顶级名称服务器发出同样的DNS查询请求报文。
- 顶级名称服务器在收到DNS查询请求之后,会首先查询本地缓存,如果有对应的域名纪录项,就会把对应的纪录项返回给DNS客户端,否则的话,就查询对应域名的二级域名的二级名称服务器信息,然后把对应的信息通过DNS应答报文返回给dns客户端,然后dns客户端会继续向上面的步骤向三级、四级名称服务器查找,直到最终的权威名称服务器找到最终的纪录项。
如果在以上流程中,对应的权威名称服务器找不到对应的记录项(如果该权威名称服务器配置了其他名称服务器转发器,就会向转发器指定的名称服务器查找),就会返回一条查询失败的报文返回给DNS客户端。如果在DNS客户端上配置了多个DNS服务器,就会继续向其它DNS服务器进行查询。