三次挥手的时候的状态转换
TCP(Transmission Control Protocol)的三次握手是建立TCP连接的过程。在三次握手中,涉及到的状态转换如下:
-
Closed(关闭状态): 初始状态,表示没有任何连接。
-
SYN_SENT(同步已发送状态): 客户端发送一个TCP报文,其中包含SYN(同步)标志位,表示请求建立连接。
-
LISTEN(监听状态): 服务器在被动打开的套接字上等待连接请求,准备接受客户端的连接。
-
SYN_RECEIVED(同步已接收状态): 服务器收到客户端的SYN报文,会回应一个包含SYN和ACK(确认)标志位的报文,表示同意建立连接。
-
ESTABLISHED(已建立连接状态): 客户端收到服务器的SYN-ACK报文后,发送一个包含ACK标志位的报文,连接建立成功。
以上是正常的三次握手过程。在三次握手中,如果某一阶段出现问题,可能会触发状态的不同转换。例如,如果客户端发送SYN后,长时间没有收到服务器的响应,可能触发超时,客户端会重新发送SYN,从而导致状态的转换。
在实际网络中,可能还涉及到一些其他状态,例如超时、重传等,这取决于网络的具体情况和TCP协议的实现。但总体上,TCP的三次握手过程涉及到以上描述的状态转换。
TCP的四次挥手是终止TCP连接的过程。在四次挥手中,涉及到的状态转换如下:
-
ESTABLISHED(已建立连接状态): 双方的数据传输已完成,开始关闭连接。
-
FIN_WAIT_1(等待对方的FIN报文状态): 主动关闭方发送一个FIN(结束)标志的报文,表示不再发送数据,但可以接收数据。
-
CLOSE_WAIT(等待被动关闭状态): 被动关闭方接收到FIN报文,通知应用层停止发送数据。
-
FIN_WAIT_2(等待对方的确认状态): 主动关闭方等待被动关闭方发送完毕数据后,发送一个带有ACK标志位的报文,确认收到了对方的FIN报文。
-
TIME_WAIT(等待足够的时间以确保被动关闭方收到了ACK): 主动关闭方等待足够的时间,确保被动关闭方已经收到了对FIN的ACK,并且该ACK不会在网络中丢失。这个状态的目的是为了处理可能出现的延迟的报文,以防止新的连接中出现旧的数据。
-
CLOSING(等待对方的确认状态): 被动关闭方在发送完ACK后,等待对方的确认,确认收到了自己的ACK。
-
LAST_ACK(等待对方的最后的ACK状态): 主动关闭方等待最后一个ACK,表示对方已经收到了主动关闭方的确认。
-
CLOSED(关闭状态): 双方的连接都已关闭。
以上是正常的四次挥手过程。在四次挥手中,如果某一阶段出现问题,可能会触发状态的不同转换。例如,如果一方在发送FIN后,长时间没有收到对方的确认,可能会触发超时,重新发送FIN,从而导致状态的转换。
2MSL ( Maximum Segment Lifetime )主动断开连接的一方, 最后进出入一个 TIME_WAIT状态, 这个状态会持续: 2mslmsl: 官方建议 : 2 分钟 , 实际是 30s当 TCP 连接主动关闭方接收到被动关闭方发送的 FIN 和最终的 ACK 后,连接的主动关闭方 必须处于TIME_WAIT 状态并持续 2MSL 时间。这样就能够让 TCP 连接的主动关闭方在它发送的 ACK 丢失的情况下重新发送最终的 ACK 。 主动关闭方重新发送的最终 ACK 并不是因为被动关闭方重传了 ACK (它们并不消耗序列号, 被动关闭方也不会重传),而是因为被动关闭方重传了它的 FIN 。事实上,被动关闭方总是 重传 FIN 直到它收到一个最终的 ACK 。
半关闭当 TCP 链接中 A 向 B 发送 FIN 请求关闭,另一端 B 回应 ACK 之后( A 端进入 FIN_WAIT_2 状态),并没有立即发送 FIN 给 A , A 方处于半连接状态(半开关),此时 A 可以接收 B 发 送的数据,但是 A 已经不能再向 B 发送数据。
从程序的角度,可以使用 API 来控制实现半连接状态:
netstat参数:
-a所有的socket
-p显示正在使用socket的程序的名称
-n直接使用IP地址,而不通过域名服务器
端口复用:
端口复用是指在一个网络应用程序中允许多个套接字共享同一个端口的能力。端口复用通常是通过设置套接字选项来实现的。在网络编程中,两个主要的套接字选项用于端口复用:
-
SO_REUSEADDR: 允许多个套接字绑定到相同的IP地址和端口号,即使先前的套接字仍然处于 TIME_WAIT 状态。这个选项通常用于服务器程序,以便更快地重新启动服务器。
-
SO_REUSEPORT: 允许多个套接字绑定到相同的IP地址和端口号。与 SO_REUSEADDR 不同的是,SO_REUSEPORT 允许多个套接字在同一台计算机上同时监听相同的 IP 地址和端口号,而不需要等待 TIME_WAIT。
端口复用最常用的用途是:
1.·防止服务器重启时之前绑定的端口还未释放·
2. 程序突然退出而系统没有释放端口
#include <sys/types.h>
#include <sys/socket.h>//设置套接字的属性(不仅仅能设置端口复用)int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen);//参数:
-sockfd:要操作的文件描述符
-1eve1: 级别-S0L_S0cKET(端口复用的级别)
-optname: 选顶的名称 SO_REUSEADDR -SO_REUSEPORT
-optva1:端口复用的值(整形)-1:可以复用-0:不可以复用-opt1en:optval:参数的大小setsockopt () bind();