当前位置:   article > 正文

网络编程3.5:理解TCP状态时序图_tcp时序图

tcp时序图

返回:Linux网络编程学习笔记

TCP状态时序图如下:

1. 三次握手(创建连接)

TCP建立连接时,三次握手时序如下:TCP数据报格式:

第一次握手:SYN, 1000(0), <mss 1460>                         

//控制位SYN置1,32位序列号为1000,该段不携带有效载荷(数据字节数为0),mss(Maximum Segment Size,最大报文长度)选项值为1460;

第二次握手:SYN, 8000(0), ACK 1001, <mss 1024>       

//控制位SYN置1,32位序列号为8000,该段不携带有效载荷,ACK置1,32位确认序列号为1001(代表client端1001之前的包,server端都收到了),mss选项值为1024;

第三次握手:ACK, 8001                                                   

//控制位ACK置1,32位确认序列号为8001(代表server端8001之前的包,client端都收到了)。

三次握手发生在内核空间,用户层的主要体现是,connect()和accept()在两端生成网络连接套接字。

使用命令查看端口状态:netstat -apn|grep 9527

  1. root@wang-virtual-machine:/home/wang/nfs# netstat -apn|grep 9527
  2. tcp 0 0 0.0.0.0:9527 0.0.0.0:* LISTEN 4087/./service
  3. tcp 0 0 127.0.0.1:9527 127.0.0.1:47286 ESTABLISHED 4087/./service
  4. tcp 0 0 127.0.0.1:47286 127.0.0.1:9527 ESTABLISHED 4088/nc

主动发起连接请求端:    CLOSE -- 发送SYN -- SEND_SYN -- 接收 ACK、SYN -- SEND_SYN -- 发送 ACK -- ESTABLISHED(数据通信态)

被动接收连接请求端: CLOSE -- LISTEN -- 接收 SYN -- LISTEN -- 发送 ACK、SYN -- SYN_RCVD -- 接收ACK -- ESTABLISHED(数据通信态)

主动发起连接                                                  被动接受连接

2. 数据传输与滑动窗口

滑动窗口:允许多发单回或多收单确认

第1至第3为建立连接阶段,sender端的滑动窗口缓冲区大小为4k,receiver端滑动窗口的缓冲区大小为6k字节;

第4至第9步,sender向receiver端发送了6次1k的数据;

第10至11步,receiver端告诉sender,缓冲区2k的数据已经处理掉了,空闲大小为4k。

第12至13步,sender向receiver再发2k的数据,并关闭了发送(半关闭);

第14至15步,为ACK应答;

第17步:receive端关闭了发送;

第18步:sender端回复了receive端关闭。

3.四次握手(关闭连接)

主动关闭连接请求端: ESTABLISHED(数据通信态) -- 发送 FIN -- FIN_WAIT_1 -- 接收ACK -- FIN_WAIT_2(半关闭)

                -- 接收对端发送 FIN -- FIN_WAIT_2(半关闭)-- 回发ACK -- TIME_WAIT(只有主动关闭连接方,会经历该状态)

                -- 等 2MSL时长 -- CLOSE 

被动关闭连接请求端: ESTABLISHED(数据通信态) -- 接收 FIN -- ESTABLISHED(数据通信态) -- 发送ACK 

                -- CLOSE_WAIT (说明对端【主动关闭连接端】处于半关闭状态) -- 发送FIN -- LAST_ACK -- 接收ACK -- CLOSE

主动发起关闭                                                   被动接受关闭

client与server建立TCP socket连接后,如果client端主动关闭连接,会进入FIN_WAIT2状态

  1. root@wang-virtual-machine:/home/wang/nfs# netstat -apn|grep 9527
  2. tcp 0 0 0.0.0.0:9527 0.0.0.0:* LISTEN 4087/./service
  3. tcp 0 0 127.0.0.1:9527 127.0.0.1:47286 CLOSE_WAIT 4087/./service
  4. tcp 0 0 127.0.0.1:47286 127.0.0.1:9527 FIN_WAIT2 -

如果server端主动关闭,其状态会从上方的CLOSE_WAIT变为FIN_WAIT2状态

  1. root@wang-virtual-machine:/home/wang/nfs# netstat -apn|grep 9527
  2. tcp 0 0 127.0.0.1:9527 127.0.0.1:47288 FIN_WAIT2 -
  3. tcp 0 0 127.0.0.1:47288 127.0.0.1:9527 CLOSE_WAIT 4143/nc

在server端主动关闭的情况下,立马重启server端,会出现以下报错信息,主要原因是FIN_WAIT2状态会持续40s,9527这个端口还在被占用。

  1. root@wang-virtual-machine:/home/wang/nfs# ./service
  2. error bind!
  3. : Address already in use

 在server的TCP连接没有完全断开之前不允许重新监听是不合理的。因为,TCP连接没有完全断开指的是connfd(127.0.0.1:47288)没有完全断开,而我们重新监听的是lis-tenfd(0.0.0.0:9527),虽然是占用同一个端口,但IP地址不同,connfd对应的是与某个客户端通讯的一个具体的IP地址,而listenfd对应的是wildcard address。解决这个问题的方法是使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP地址不同的多个socket描述符。
        在server代码的socket()和bind()调用之间插入如下代码:

  1.     int opt = 1;
  2.     setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

有关setsockopt可以设置的其它选项请参考UNP第7章。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/158781
推荐阅读
相关标签
  

闽ICP备14008679号