TCP同步而UDP没有,就导致TCP是有连接,而UDP是无连接的
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
客户端与服务器端将保持活动状态,直到任何一方发送FIN(结束)信号
TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文
(1)首先客户端向服务器端发送一段TCP报文,其中:
标记位为SYN,表示“请求建立新连接”;
序号为seq=X(X一般为1);
随后客户端进入SYN-SENT阶段。
(2)服务器端接收到来自客户端的TCP报文之后,结束LISTEN阶段。并返回一段TCP报文,其中:
标志位为SYN和ACK,表示“确认客户端的报文seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”(即告诉客户端,服务器收到了你的数据);
序号为seq=y;确认号为ack=x+1,表示收到客户端的序号seq并将其值加1作为自己确认号ack的值;随后服务器端进入SYN-RCVD阶段。
(3)客户端接收到来自服务器端的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段。并返回最后一段TCP报文。其中:
标志位为ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了);
序号为seq=x+1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值;
确认号为ack=y+1,表示收到服务器端序号seq,并将其值加1作为自己的确认号ack的值;随后客户端进入ESTABLISHED阶段。服务器收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器到客户端的数据传输是正常的。结束SYN-SENT阶段,进入ESTABLISHED阶段。
在客户端与服务器端传输的TCP报文中,双方的确认号ack和序号seq的值,都是在彼此ack和seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成。
此后客户端和服务器端进行正常的数据传输。这就是“三次握手”的过程。
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
在上面的模型当中,我们之所以觉得算法不好设计,是因为用错了数据结构。有个说法叫作如果程序写复杂了,那就是写错了。这里其实应该用一种叫作滑动窗口的数据结构去实现。
如上图所示:
深绿色代表已经收到 ACK 的段,浅绿色代表发送了,但是没有收到 ACK 的段,白色代表没有发送的段,紫色代表暂时不能发送的段
下面我们重新设计一下不同类型封包的顺序,将已发送的数据放到最左边,发送中的数据放到中间,未发送的数据放到右边。假设我们最多同时发送 5 个封包,也就是窗口大小 = 5。窗口中的数据被同时发送出去,然后等待 ACK。如果一个封包 ACK 到达,我们就将它标记为已接收(深绿色)。
如下图所示,有两个封包的 ACK 到达,因此标记为绿色。
这个时候滑动窗口可以向右滑动,如下图所示:
TCP数据的重传机制,就导致TCP是可靠的传输,而UDP不具备这样的能力,是一个不可靠的传输
起初,假定发送端拥塞窗口尺寸为3,含义为:在收到对方的确认之前可以连续发送3个字节,同时假定接收方通告的窗口大小也是3,取两者的最小值作为发送窗口尺寸,结果是3.
因此图中那个发送者发送完3字节后等待接收方确认。接收方由于缓冲区变化造成第3字节的数据被丢弃,因此接收方在返回给发送者的确认数据中只提示收到2字节。确认码为3表示收到2字节,等待第3个。
同时接收方在它的确认数据中将窗口尺寸改为2,这个数值是由TCP头中的窗口字段表示的。发送方收到这个确认后得知第3字节丢失,重新传送第3字节的内容,并且调整发送窗口尺寸为两者中的最小者,结果是2.这样将解决丢包现象。
如果发送过程中,部分数据没能收到 ACK 会怎样呢?这就可能发生重传。
如果发生下图这样的情况,段 4 迟迟没有收到 ACK。
这个时候滑动窗口只能右移一个位置,如下图所示:
在这个过程中,如果后来段 4 重传成功(接收到 ACK),那么窗口就会继续右移。如果段 4 发送失败,还是没能收到 ACK,那么接收方也会抛弃段 5、段 6、段 7。这样从段 4 开始之后的数据都需要重发。
在 TCP 协议中,如果接收方想丢弃某个段,可以选择不发 ACK。发送端超时后,会重发这个 TCP 段。而有时候,接收方希望催促发送方尽快补发某个 TCP 段,这个时候可以使用快速重传能力。
例如段 1、段 2、段 4 到了,但是段 3 没有到。 接收方可以发送多次段 3 的 ACK。如果发送方收到多个段 3 的 ACK,就会重发段 3。这个机制称为快速重传。这和超时重发不同,是一种催促的机制。
为了不让发送方误以为段 3 已经收到了,在快速重传的情况下,接收方即便收到发来的段 4,依然会发段 3 的 ACK(不发段 4 的 ACK),直到发送方把段 3 重传。
参考自:
https://blog.csdn.net/m0_56649557/article/details/119492899
https://kaiwu.lagou.com/course/courseInfo.htm?courseId=837#/detail/pc?id=7268
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。