tcp特性:面向连接特性(三握四挥)

面向连接

三次握手

重重点:
SYN代表发送者可以收发数据
FIN代表对方不再发送数据

为什么是三次握手

  • 握手是双方都要确保对方有收发数据的能力,因此都要发送SYN请求

  • 两次不行:两次是不安全
    状态要求:SYN延迟到达,与重发的SYN冲突,通过三次握手的不同状态,让两端做不同的事情,遇见同样的SYN则丢弃

  • 防止恶意攻击,客户端发送SYN就退出,占用服务器资源

  • 四次没必要

握手失败两端的处理

  • 第一次连接丢了,客户端重发
  • 第二次连接丢了,客户端重传,服务端等不到ACK就会发送RST报文,服务端断开连接
  • 第三次连接丢了,服务器没收到ACk,释放资源

1.从双方连接状态的角度

  • 两次握手时,服务端认为该连接不是建立的
    该连接还在内核的未完成队列中;
  • 即使程序员调用accept函数也不会将连接从内核中获取

2.从客户端接收能力角度

  • 客户端发送SYN,服务端收到则认为客户端可以发送
  • 服务端发送ACK+SYN,客户端收到则认为服务端可以收发数据
    这个ACK说明服务端可以收发数据
  • 客户端发送ACK,服务端收到则认为客户端可以接收
    这个ACK说明客户端可以收发数据
    不发,则服务端不确定客户端是否能收发数据

在这里插入图片描述

  • 对于客户端,状态是 ESTEBALISHED则连接建立;
  • 此时服务端状态是 SYN_RCVD,认为连接未建立;
  • 当前连接还在内核未完连接成队列中,即使服务端调用accept也不会将连接从内核中拿回;
  • 只有客户端回复ACK,状态变成 ESTEBALISHED,连接才建立,
    服务端调用accept函数才能从已完成队列中取回连接

四次挥手

四次挥手,双方都有可作为主动断开方

  • 问题1:为什么是四次挥手
    FIN的功能,只代表对方不再发送数据,不代表对方不接收数据
    被动关闭方收到FIN确认后,还有可能继续发数据,上层没数据了,才关闭套接字
    因此没有合并成三次
  • 问题2:出现大量CLOSE_WAIT状态的原因
    该状态的下一步是关闭连接
    连接断开后,上层没有关闭套接字,是代码的问题
  • 问题3:TIME_WAIT状态的作用,为什么不直接关闭套接字资源
    需知:MSL(默认60秒)是报文最大生命周期
    分析:最后一次ACK可能丢失,未收到ACK会重传FIN包
    主动方直接关闭套接字,此时主动方别的程序启用该端口,就可能和当前服务器进行通信,直接收到一个FIN包
    等待2MSL后,保证上一次通信的所有数据包都丢失在网络中,不影响后续的通信

问题4:出现大量TIME_WAIT状态的原因

  • TIME_WAIT的作用:
    TIME_WAIT状态是主动方发送最后一次ACK后进入的状态,等待是为了处理因FIN包丢失重传
    等待2MSL时间,防止最后一次ACK丢失重传FIN包影响新连接
  • 产生原因:
    主机上存在大量主动关闭的连接
    一台主机最多有65536个端口,就只能创建这么多客户端
  • 如何解决
    可以将TIME_WAIT时间缩短

如果服务器是主动关闭方,大量程序处于wait状态,是非常危险的(服务器崩溃无法重启),应采用地址重用
地址重用:当前连接虽然使用了该端口,但是其它连接仍可使用,setsocketopt函数

问题5:

在这里插入图片描述

保活机制

两端通信频率低,但是网断了(没有四次挥手),两端如何知道连接断开
连接断开的信息:recv返回0,send会发送异常

若长时间没通信(默认7200秒),tcp服务器会自动发送保活心跳包(每75秒发送一次包,连发9次),若对方没响应就断开

包序管理

网络抓包

要了解包序管理,就要先进行网络抓包:

1.win环境,使用wireshark针对网卡进行抓包
2.linux环境,使用tcpdump,可以抓任意协议的数据包

  • 命令:tcpdump -i any port [要抓取的数据端口] -s 0 -w 123.dat
    any表示所有网卡都需抓取
  • 123.dat抓到的数据所写入的文件
  • 将这些文件在wireshark分析

三次握手阶段

三次握手建立连接后,双方并不能正常发送数据

序号:tcp将发送的每个字节数据进行了编号,即序列号

  • 双方都有各自的序号,谁发送数据的时候,就使谁的序号标识数据;
  • 接收方收到数据后,会进行确认,确认方式是 “期望收到对方发送的下一个序号数据包” ;

在这里插入图片描述

  • ack是确认收到上一序号消息 + 期望下次收到的信息序号
  • seq标识本端是从哪个序号发送信息的
  • tcp双方在发送数据时,数据的每个字节都有序号进行标识

纯ACK数据包(上图中第二次连接是ACK+SYN包,第三次连接是纯ACK包)不消耗序号,也就不需要对方确认,
例如:
对方确认序号是多少,我下次的发送起始序号是多少在这里插入图片描述
结论:

  1. 在三次握手中,双方协商各自维护序号的起始位置
  2. 双方在发送数据时是消耗自己的序号,确认对方序号
  3. 纯ACK数据包不消耗序号
  4. tcp针对发送的数据,每一个字节都会消耗一个序号

四次挥手阶段

MSL:报文最大生存时间(自发送方发送数据后,发送方认为该报文最大生存时间是MSL);

主动方收到后重置MSL,产生新的TIME_WAIT状态继续等待2MSL;

正常到达状态:

  • 主动断开方等待了2MSL的时间,还未等到重传的FIN报文,说明ACK数据一定到达了被动方;
  • 多等一个MSL是保证被动断开方重传FIN能到达主动方

在这里插入图片描述只有主动断开连接方才存在TIME_WAIT状态;

处于TIME_WAIT状态的程序,还需要占用端口,等待2MSL后释放端口,这是要防止被动断开方重传FIN报文

端口重用:

  • 主动断开方处于TIME_WAIT状态会等待2MSL时间变成CLOSED,但是这个时间内,这个应用程序虽然退出,但是操作系统还依旧使用着端口(程序中的端口是写死的);
  • 在这个时间内再次快启动该程序就会出现问题,报错:bind:Address already in ues
    需要在该代码中使用setsockopt函数提前将端口设置为重用状态

在这里插入图片描述

CLOSED_WAIT状态

  • 被动断开方才有的状态;
  • 处于CLOSED_WAIT状态的被动断开方,需要调用close函数关闭新连接套接字,只有调用后才能变成LAST_ACK状态;
  • 在这个状态变化过程中,被动断开方还可以给对端发送一些数据
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值