TCP学习-2
TCP学习(二)
连接建立 - 三次握手 - 沟通双方的初始序列号
- 请求端发送SYN段,包含发端初始序号(ISN-C),以及服务器端口,MSS
- 服务器通过发送SYN进行响应:包含收端初始序号(ISN-S),ACK被设置为1作为对请求端SYN的确认,确认序号 = ISN-C + 1, MSS
- 请求端发送ACK,响应服务器的SYN:ACK被设置为1作为对服务器SYN的确认,确认序号 = ISN-S + 1
此外,连接建立的过程还会沟通MSS的具体数值,以避免分片的产生;但是只能沟通收发两端,无法避免链路中间节点的分片行为;此时就需要路径上的MTU发现机制
连接终止 - 四次挥手
全关闭 - 主动关闭 + 被动关闭
发送第一个FIN的一方将执行主动关闭,而另一方执行被动关闭
- A首先发送FIN,包含序列号
seq-A; - B收到该FIN后,返回确认:ACK被设置为1,确认序列号为
seq-A + 1; -> 由TCP协议栈内部逻辑处理进行发送
一般地,B会向其应用程序递送一个EOF【文件结束符】,接着B的应用程序就关闭该TCP连接,导致 - B主动发一个FIN,序号为
seq-B; - A收到该FIN后,返回确认:ACK被设置为1,确认序列号为
seq-B + 1; -> 由TCP协议栈内部逻辑处理进行发送
小结
- 可以看到,终止的过程和建立的过程在第一次回复时略有不同:
- 连接时,第一次回复带有SYN信息,用于沟通B端的初始序列号
- 终止时,第一次回复仅是简单的回复 -> 是否可能将第二次FIN与第一次ACK进行压缩呢?
半关闭
- TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力,这就是所谓的半关闭;需要注意,TCP是双向连接的,因此可以只关闭单方向的连接,而发送FIN的一端即主动关闭该方->对方的数据发送通道,但是对方数据发送-本地数据接收还是正常的
- 为了使用这个特性,必须为用户提供一个编程接口,且该接口表明:我已经完成了数据传送,因此发送一个文件结束(FIN)给另一端,但我还想接收另一端发来的数据,直到它给我发来文件结束(FIN)
- 如果应用程序不调用close而调用
shutdown,且第2个参数值为1,则插口的API支持半关闭。然而,大多数的应用程序通过调用close终止两个方向的连接
建立与终止过程中的状态迁移
参考《TCPIP详解:卷1》18.6节
关闭时:
- 被动关闭:接收到FIN,则进入
close_wait状态,等待本地应用程序关闭socket,进而发送FIN进入last_ack状态,等待对端的ACK;接收到ACk后,连接被彻底关闭 - 主动关闭:
- 应用进程主动调用
close()等关闭连接,首先发送FIN,进入fin_wait_1状态; - 收到对端的ack后,进入
fin_wait_2状态; - 之后等待对端发送FIN,进而回复ACK,进入
time_wait状态 - 2MSL(报文段最大生存时间)后,连接彻底关闭
- 应用进程主动调用
- 被动关闭:接收到FIN,则进入
2MSL等待状态
- MSL:报文段最大生存时间MSL(Maximum Segment Lifetime)
- 该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)
- 在连接处于2MSL等待时,任何迟到的报文段将被丢弃
- 只有主动关闭连接的一端会进入该状态;而且服务器端,客户端都可以主动关闭连接
当有多个连接请求时
- 服务器来不及处理这么多连接请求,将会把完成三次握手的连接放到内核中的连接队列中
- 如果队列已经满了,则服务器端TCP协议栈将不理会新来的SYN报文,也不会发回RST
- 因此后续客户端会重传其SYN,直至与服务器完成连接的建立
TCP学习-2
http://example.com/2024/07/22/TCP学习-2/