0%

TCP通信[未完成]

简介

传输控制协议( TCP : Transmission Control Protocol ),是一种面向连接的,可靠的传输层控制协议。

面向连接

一般,客户端发送给服务端的一个数据包携带的数据最大为1460字节。是因为,以太网帧结构数据长度是1500字节,其中包含20字节的IP头部以及20字节的TCP头部,所以数据能够携带1460字节。

三次握手

三次握手,由内核完成。反应在程序中,是由客户端程序的 connect() 开始,由 服务端程序的 accept() 返回结束。

示例

1
2
3
4
5
6
7
8
9
客户端发送:SYN 1000(0) win 4096 <mss 1460>
服务端发送:SYN 8000(0) win 6144 ACK 1001 <mss 1024> //ACK 1001 是接收到的序号+数据字节(SYN标志位也得占1字节)
客户端发送:ACK 8001 win 4096

/*
** (0) : 表示携带数据为0字节
** win 4096 : 发送端滑动窗口缓存4096字节
** <mss 1460> : 表示携带数据最大字节数为1460字节
*/

总结

1
2
3
主动发起连接请求端:发送SYN标志位,请求建立连接。携带数据包包号,数据字节数(0),滑动窗口大小
被动接受连接请求端:发送ACK标志位,同时携带SYN请求标志位。携带序号,确认序号,数据字节数(0),滑动窗口大小
主动发起连接请求段:发送ACK标志位,应答服务器连接请求。携带确认序号。

要点

为什么不是二次握手?

  1. 彼此确定收发能力
  • 第一次客户端发送请求,服务端接收请求:服务端知道了客户端有发送的能力。
  • 第二次服务端发送请求,客户端接收请求:客户端知道了服务端有收发的能力。
  • 此时,服务端不知道客户端是不是有接收的能力。因此需要客户端再次告知服务端。
  1. 避免两次连接
  • 客户端发送的连接请求如果滞留在网络中,等到超时重传,会再次发起连接请求,而服务器接收到两个连接请求会打开两个连接。因此,需要三次握手。

第三次客户端发送ACK时,可以携带数据

  • 因为此时,客户端服务端都知道双方都有收发数据的能力,所以可以开始通信。

四次挥手

四次挥手,目的是断开客户端到服务端的全双工链路。断开一端称为半关闭,会关闭一端的套接字的一个缓存区。

示例

1
2
3
4
客户端发送:FIN 501(0)  ACK 701 
服务端发送:ACK 502 ---- 半关闭
服务端发送:FIN 701(0) ACK 502
客户端发送:ACK 702 ---- 完全断开

总结

1
2
3
4
主动关闭连接请求端:发送FIN标志位。
被动关闭连接请求端:应答ACK标志位。 ———— 半关闭完成
被动关闭连接请求端:发送FIN标志位。
主动关闭连接请求端:应答ACK标志位。 —————连接全部关闭

客户端接收到服务器的应答之后,进入半关闭状态,不能发送数据给服务器,而服务器会在发送完剩余数据后,发起关闭请求,客户端应答服务器后需要等待 2MSL(最大报文存活时间)后释放连接。原因如下:

  • 如果客户端的应答数据包丢失,那么服务器会再次发送断开请求。
  • 等待一段时间,使本次连接过程中产生的数据包在网络中消失。

可靠传输

超时重传

TCP使用超时重传来实现可靠传输:如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段。

一个报文段从发送到接收到确定所经历的时间称为往返时间RTT(加权平均RTTs)。超时时间 RTO 应该略大于 RTTs 。TCP使用的超时时间计算是 : RTO = RTTs + 4 * RTTd 。RTTd : 偏差的加权平均值。

滑动窗口

滑动窗口是一个缓存区,用于暂时存放字节流。发送方和接收方各有一个窗口,接收方通过TCP报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其他信息来设置自己的窗口大小。

对于发送方来说,当窗口靠左侧的数据包已经成功发送并被确认后,窗口向右滑动直到某一个未发送或者未确认的字节位置。

对于接收方来说,当窗口靠左侧的数据包已经收到,窗口向右滑动直到某一个未接收到的字节。

流量控制

流量控制是为了控制发送方发送速率,保证接收方来得及接收。

接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

拥塞控制

如果网络出现拥塞,发送方发送的数据包丢失,发送方重传导致网络难以恢复。因此要进行一定的拥塞控制使得发送方降低发送速率。发送方需要维护一个拥塞窗口(cwnd)状态变量:决定发送方能发送多少数据。

慢开始与拥塞避免

发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …

注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。

如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。

快速重传与快速恢复

在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。

在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。

在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。

慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。

-------------本文结束, 感谢您的阅读, 如有问题欢迎联系我-------------