【网络篇】开发必备知识点:UDP/TCP协议

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

前言

记得第一次学习网络相关知识是在大学的时候,那时候计算机网络计算机组成原理操作系统数据结构统称为四大天书,每一科都是厚厚的一本,妥妥的劝退。以至于在后面工作中碰到问题只知其然而不知其所以然,愈来愈发现基础才是王道

以下是最近在重温计算机网络时记下的知识点,后续的想法是写成一个系列,基础->OkHttp->Retrofit等网络框架源码解析,请敬请期待。

目录

一、UDP用户数据报协议

  • 1.1、UDP的主要特点
  • 1.2、UDP的首部格式
  • 1.3、UDP首部中如何计算‘检验和’?

二、TCP传输控制协议

  • 2.1、TCP的特点
  • 2.2、TCP报文段的首部格式
  • 2.3、为什么TCP能可靠的传输数据?
  • 2.4、什么是流量控制?
  • 2.5、TCP如何实现流量控制?
  • 2.6、什么是TCP的拥塞控制?
  • 2.7、如何进行拥塞控制?
  • 2.8、TCP的三次握手
  • 2.9、为什么三次握手最后还要发送一次确认?
  • 2.10、TCP的四次挥手
  • 2.11、为什么四次挥手最后客户端在TIME-WAIT状态必须等待2MSL的时间?

一、UDP用户数据报协议

1.1、UDP的主要特点

(1) UDP是无连接的,即发送数据前不需要建立连接,因此减少了开销和发送数据前的时延;

(2) UDP使用尽最大努力交付,即不保证可靠的数据传输,因此主机不需要维持复杂的连接状态表;

(3) UDP是面向报文的,应用层交给UDP多长的报文,UDP既不合并也不拆分,照样发送,即一次发送一个整报文;

(4) UDP没有拥塞控制

(5) UDP支持一对一、一对多、多对一、多对多的交互通信

(6) UDP首部开销小,只有8个字节,而TCP有20个字节。

1.2、UDP的首部格式

用户数据报UDP有两个字段:数据字段和首部字段。首部字段很简单,只有8个字节(下图),由四个字段组成,每个字段的长度都是两个字节。

image.png

(1) 源端口,在需要对方回信时选用。不需要时可用全0;

(2) 目的端口,这在终点交付报文时必须要使用到;

(3) 长度,UDP用户数据报的长度,其最小值是8(仅有首部);

(4) 检验和,检测UDP用户数据报在传输中是否有错。有错就丢弃。

1.3、UDP首部中如何计算‘检验和’?

在计算检验和时,要在UDP用户数据报之前增加12个字节的伪首部。所谓“伪首部”是因为这种伪首部并不是UDP用户数据报真正的首部。只是在计算检验和时,临时添加在UDP用户数据报前面,得到一个临时的UDP用户数据报。检验和就是按照这个临时的UDP用户数据报来计算的。伪首部既不向下传送也不向上递交,而仅仅是为了计算检验和。

在发送方,首先是先把全零放入检验和字段。再把伪首部以及UDP用户数据报看成是由许多16位的字串接起来。若UDP用户数据报的数据部分不是偶数个字节,则要填入一个全零字节(但此字节不发送)。然后按二进制反码计算出这些16位字的和。将此和的二进制反码写入检验和字段后,就发送这样的UDP用户数据报。在接收方,把收到的UDP用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些16位字的和。当无差错时其结果应为全1。否则就表明有差错出现,接收方就应丢弃这个UDP用户数据报(也可以上交给应用层,但附上出现了差错的警告)。

二、TCP传输控制协议

2.1、TCP的特点

(1) TCP是面向连接的运输层协议。这就是说,应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接;

(2) 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一);

(3) TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达;

(4) TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据;

(5) 面向字节流。应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。
image.png
TCP并不关心应用进程一次把多长的报文发送到TCP的缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP发送的报文长度是应用进程给出的)。如果应用进程传送到TCP缓存的数据块太长,TCP就可以把它划分短一些再传送。如果应用进程一次只发来一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

2.2、TCP报文段的首部格式

TCP传送的数据单元是报文段。一个TCP报文段分为首部数据两部分,而TCP的全部功能都体现在它首部中各字段的作用。

image.png

TCP报文段首部的前20个字节是固定的,最小长度是20字节。

首部固定部分各字段的意义如下:

(1) 源端口和目的端口,各占2个字节,分别写入源端口号和目的端口号;

(2) 序号,占4字节首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号。例如,一报文段的序号字段值是301,而携带的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401;

(3) 确认号,占4字节是期望收到对方下一个报文段的第一个数据字节的序号例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;

(5) 数据偏移,占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远;

(6) 保留,占6位;

(7) 紧急URG ,当URG = 1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送;

(8) 确认ACK(ACKnowlegment),仅当ACK = 1时确认号字段才有效。当ACK = 0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1;

(9) 推送PSH,当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH = 1的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付;

(10) 复位RST (ReSeT),当RST = 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。RST也可称为重建位或重置位;

(11) 同步SYN,当SYN = 1而ACK = 0时,表明这是一个连接请求报文段,对方若同意建立连接,则应在响应的报文段中使SYN = 1和ACK = 1。SYN置为1就表示这是一个连接请求或连接接受报文;

(12) 终止FIN ,用来释放一个连接。当FIN = 1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接;

(13) 窗口,占2字节。窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。之所以要有这个限制,是因为接收方的数据缓存空间是有限的;

(14) 检验和,占2字节,检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部;

(15) 紧急指针,占2字节。紧急指针仅在URG = 1时才有意义,它指出本报文段中的紧急数据的字节数,因此,紧急指针指出了紧急数据的末尾在报文段中的位置;

2.3、为什么TCP能可靠的传输数据?

可靠的传输条件有以下两个特点:

(1) 传输信道不产生差错。

(2) 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。

TCP利用检验和连接管理机制ACK应答机制快速重传超时重传机制滑动窗口机制拥塞控制机制流量控制机制,这些机制共同保证TCP协议的可靠性。

2.4、什么是流量控制?

如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

2.5、TCP如何实现流量控制?

一般说来,我们总是希望数据传输得更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。所谓流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。

TCP利用滑动窗口机制实现对发送方的流量控制。设A向B发送数据。在连接建立时,B告诉了A:“我的接收窗口rwnd = 400”。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。

2.6、什么是TCP的拥塞控制?

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫做拥塞。而所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。

2.7、如何进行拥塞控制?

(1) 利用慢开始和拥塞避免算法

慢开始算法是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。经验证明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。

拥塞避免算法是让拥塞窗口cwnd缓慢地增大,在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。

(2) 利用快重传和快恢复算法

快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段。如接收方收到了M1和M2后都分别发出了确认。现假定接收方没有收到M3但接着收到了M4。显然,接收方不能确认M4,因为M4是收到的失序报文段(按照顺序的M3还没有收到)。根据可靠传输原理,接收方可以什么都不做,也可以在适当时机发送一次对M2的确认。但按照快重传算法的规定,接收方应及时发送对 M2的重复确认,这样做可以让发送方及早知道报文段M3没有到达接收方。发送方接着发送M5和M6。接收方收到后,也还要再次发出对M2的重复确认。这样,发送方共收到了接收方的四个对M2的确认,其中后三个都是重复确认。

2.8、TCP的三次握手

image.png

SYN ACK FIN等含义请参考【2.2、TCP报文段的首部格式】

(1) 第一次握手:A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,这时首部中的同步位SYN = 1,同时选择一个初始序号seq = x。TCP规定,SYN报文段(即SYN = 1的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP客户进程进入SYN-SENT(同步已发送)状态;

(2) 第二次握手:B收到连接请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号是ack = x + 1,同时也为自己选择一个初始序号seq = y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时TCP服务器进程进入SYN-RCVD(同步收到)状态;

(3) 第三次握手:TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack = y + 1,而自己的序号seq = x + 1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq = x + 1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。

2.9、为什么三次握手最后还要发送一次确认?

现假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。

2.10、TCP的四次挥手

image.png

(1) 第一次挥手: A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置1,其序号seq = u,它等于前面已传送过的数据的最后一个字节的序号加1。这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认;

(2) 第二次挥手: B收到连接释放报文段后即发出确认,确认号是ack = u + 1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭(half-close)状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一些时间。A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段;

(3) 第三次挥手: B发出连接释放报文段,必须使FIN = 1。现假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack = u + 1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

(4) 第四次挥手: A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack = w +1,而自己的序号是seq = u + 1(。然后进入到TIME-WAIT(时间等待)状态。

请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命(Maximum Segment Lifetime)。

2.11、为什么四次挥手最后客户端在TIME-WAIT状态必须等待2MSL的时间?

(1) 为了保证A发送的最后一个ACK报文段能够到达B。 这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN + ACK报文段的确认。B会超时重传这个FIN + ACK报文段,而A就能在2MSL时间内收到这个重传的FIN + ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN + ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按照正常步骤进入CLOSED状态;

(2) 防止已失效的连接请求报文段出现在本连接中,与第八个问题【八、为什么三次握手最后还要发送一次确认?】一致。A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。

以上

参考资料:

《计算机网络》第7版-谢希仁

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享