三次握手-四次挥手

1.TCP

​ TCP 是一种面向连接的单播的,可靠的,流式传输协议,位于网络模型的传输层,为应用程序间提供数据传输。

2.TCP 连接的建立和终止

TCP三次握手 四次挥手
  • 1.服务器调用socket,bind ,listen 完成初始化,服务器做好准备等待外部的TCP连接的到来,这种方式为被动打开,这个时候服务器处于LISTEN状态,等待客户端的连接请求。
  • 2.客户端通过connect发起主动打开,向服务器发出连接请求,发送请求标识位SYN=1,同时发送初始化序号seq=x.SYN报文不允许携带数据,消耗一个序号。此时客户端进入SYN-SEND 状态
  • 3.服务器接收到客户端的请求,需要确认客户端的报文端,在确认报文中把SYN和ACK都置为1。确认号是:ack = x+1,同时服务器向客户端发起连接请求,初始化序号seq=y.服务器进入SYN-RECVIVED(同步收到)状态。
  • 4.客户端在收到服务器发出的响应后,给出确认连接,置ACK=1,seq =y+1,ack=y+1.此时客户端进入ESTABLISHED状态.
  • 5.服务器收到客户端的确认后,也进入了ESTABLISHED状态.

总结:

服务器状态变化:LISTEN—>SENT-RECVIVED—>ESTABLISHED

客户端状态变化:SYN-SEND—>ESTABLISHED

  • 1.客户端发出断开连接请求,停止发送数据,主动关闭TCP连接。客户端发送FIN,请求断开连接,序号为seq=u,此时客户端进入FIN-WAIT-1(终止等待1)状态
  • 2.服务器接收到客户端的断开连接请求,发出确认报文,置ACK=1.生成自己的序号seq=v,回复ack=u+1.服务器进入CLOSE-WAIT(关闭等待)状态
  • 3.客户端收到服务器的确认后,就会进入FIN-WAIT-2(终止等待2)状态。
  • 4.服务器发出断开连接的FIN,发送完断开连接请求之后,服务器主动进入了LAST-ACK(最后确认)状态。
  • 5.客户端收到服务器的断开连接请求,客户端发出确认断开连接。客户端进入TIME_WAIT(时间等待)阶段,经过2MSL,客户端进入CLOSED状态。
  • 6.服务器收到客户端的断开连接确认后,进入CLOSED状态。服务器结素TCP连接的时间要比客户端早。

3.TCP半关闭

TCP半关闭指关闭了数据流的一个传输方向。在TCP半关闭的场景:我已经完成了数据发送,给对方发送了FIN,此时就是处于半关闭状态,这个状态下,我还继续可以接受对方的数据,但是我无法发送数据,知道对方发给我一个FIN,这个状态才会发生变化。

//设置半关闭的状态
#include <sys/socket.h>
int shutdown(int sockfd,int how);
  • 参数:

    • sockfd: 要操作的文件描述符(socket的返回值)

    • how

      • SHUT_RD 关闭文件描述符对应的读操作
      • SHUT_WR 关闭文件描述符对应的写操作
      • SHUT_RDWR 关闭文件描述符对应的读写操作
    • 返回值:

      • 成功 0 ,失败 -1

4.TIME_WAIT状态

​ 主动关闭连接的一方会进入TIME_WAIT状态。这个状态会等待2MSL,也就是最大段生存周期时间的两倍。

MSL是TCP段期望的最大生存时间。也就是网络中存在的最长时间。当TCP发送完最后的ACK后,等待2MSL时间后才会退出,这样能够让TCP重新发送最终的ACK以避免丢失的情况。重新发送最终的 ACK 并不是因为客户端要重传了ACK,而是因为服务器重传了 FIN,服务器经常回发送 FIN,因为它需要 ACK 的响应才能够关闭连接,如果生存时间超过了 2MSL 的话,客户端就会发送 RST,使服务端出错。(主动关闭方重新发送的最终ACK,是因为被动关闭方重传了它的FIN。事实上,被动关闭方总是重传FIN直到它收到一个最终的ACK。)

//由于2MSL的等待时间,所以一个端口段时间的启用,会报端口已占用,无法启动服务器
//设置端口复用

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
/*
sockfd 要操作的文件描述符(socket的返回值)
level:端口复用需要使用 SOL_SOCKET 宏
optname: SO_REUSEADDR 或者 SO_REUSEPORT
optval: 0 不设置。1设置
optlen: optval 指针指向的内存大小 sizeof (int)

int op = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,op,sizeof(op));

*/

5.状态转换

TCP状态转换图

客户端

  • 第一次握手:发送 SYN,没有状态 -> SYN_SENT
  • 第二次握手:收到回复的 ACK,SYN_SENT -> ESTABLISHED
  • 主动断开连接,第一次挥手发送 FIN,状态 ESTABLISHED -> FIN_WAIT_1
  • 第二次挥手,收到 ACK,状态 FIN_WAIT_1 -> FIN_WAIT_2
  • 第三次挥手,收到 FIN,状态 FIN_WAIT_2 -> TIME_WAIT
  • 第四次挥手,回复 ACK,等待 2 倍报文时长之后,状态 TIME_WAIT -> 没有状态

服务器
启动监听,没有状态 -> LISTEN
第一次握手,收到 SYN,状态 LISTEN -> SYN_RCVD
第三次握手,收到 ACK,状态 SYN_RCVD -> ESTABLISHED
收到断开连接请求,第一次挥手状态 ESTABLISHED -> CLOSE_WAIT
第三次挥手,发送 FIN 请求和客户端断开连接,状态 CLOSE_WAIT -> LAST_ACK
第四次挥手,收到 ACK,状态 LAST_ACK -> 无状态(没有了)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值