Linux 网络编程 全解(五)--------TCP状态切换

版权声明:本BLOG上原创文章未经本人许可,不得转载,否则属于侵权行为 https://blog.csdn.net/weixin_40204595/article/details/83212197

写在前面:

Linux 网络编程 全解(一)--------网络基础协议

Linux 网络编程 全解(二)--------套接字socket

Linux 网络编程 全解(三)--------TCP三次握手、数据传输、四次挥手、滑动窗口

Linux 网络编程 全解(四)--------多进程并发服务器和多线程并发服务器

正文:

一、TCP状态切换
先贴一张TCP的状态转换图,如下:

 

图中:实线部分为主动发起的,虚线部分为被动相应的。

1、先来看主动发起连接请求(一般是client)的状态变化:

                                        发送SYN                                               接受对端的SYN+ACK,并发送给对端ACK
    有原来的close态 -------------------------->成为SYN_SENT态--------------------------------------------------------------------------->成为

ESTABLISHED态,即数据通信态。

  2、主动关闭连接请求状态变化:

                                                  发送FIN标志                                      对端回复ACK之后
      原来为ESTABLISHED--------------------------->成为FIN_WAIT_1态--------------------------->成为FIN_WAIT_2

                                                             收到对端的FIN并给对端发送ACK之后                                       等待2MSL时长之后
态(FIN_WAIT_2就是半关闭状态)-------------------------------------------------------->成为TIME_WAIT态---------------------------------------

------>重新回到 close态


   注意:只有主动关闭连接方才会经历TIME_WAIT状态,才会经历TIME_WAIT之后的等待2MSL时长的状态。


 2MSL TIME_WAIT存在的意义:让 4 次握手关闭流程更加可靠; 4 次握手的最后一个 ACK 是是由主动关闭方发送出去的,若这个 ACK 丢失,被动关闭方会再次发一个 FIN 过来。若主动关闭方能够保持一个 2MSL 的 TIME_WAIT 状态,则有更大的机会让
丢失的 ACK 被再次发送出去。 RFC(Request For Comments) 793 中规定 MSL 为 2 分钟,实际应用中常用的是 30 秒, 1 分钟和 2 分钟等

3、被动接受连接(一般是server)

                                     一起来就成为                  接收到对端的SYN并发送SYN+ACK之后                        对端回复ACK之后
       有原来的close态----------------------->listen态------------------------------------------------->成为SYN_RCVD态----------------------->成

为ESTABLISHED态

4、被动关闭连接

                        对端发送FIN标志,并给对端回复ACK之后                                                                       给对端发送FIN标志之后  
  原来为ESTABLISHED------------------------------------------>成为CLOSE_WAIT状态(说明对端已经进入半关闭状态)-----------------> 
     

                                         接受到对端的ACK之后
成为LAST_ACK状态--------------------------------->成为close状态

二、其他的几个 补充点:

1、端口复用函数

    在 server 代码的 socket()和 bind()调用之间插入如下代码
    int opt = 1;// 1:设置端口复用,0:设置端口不复用
    int setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,&opt, sizeof(opt));


 2、shutdown函数
    int shutdown(int sockfd, int how);
    sockfd: 需要关闭的 socket 的描述符
    how: 允许为 shutdown 操作选择以下几种方式:
    SHUT_RD(0): 关闭 sockfd 上的读功能,此选项将不允许 sockfd 进行读操作。
                            该套接字不再接受数据,任何当前在套接字接受缓冲区的数据将被无声的丢弃掉。
    SHUT_WR(1): 关闭 sockfd 的写功能,此选项将不允许 sockfd 进行写操作。 进程不能在对此套接字发出写操作。
    SHUT_RDWR(2): 关闭 sockfd 的读写功能。 相当于调用 shutdown 两次:首先是以 SHUT_RD,然后以 SHUT_WR
 

猜你喜欢

转载自blog.csdn.net/weixin_40204595/article/details/83212197