Linux网络编程(传输层协议 )—tcp三次握手/四次挥手
Posted AllenSquirrel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux网络编程(传输层协议 )—tcp三次握手/四次挥手相关的知识,希望对你有一定的参考价值。
传输层协议:负责应用程序之间数据传输-TCP/UDP
UDP协议:
16位源端-对端端口:用于描述识别通信两端进程
16位数据报长度:能够存储最大数字 65535,(udp报文总大小不超过64k)
16位校验和:二进制反码求和算法——校验接收方接收到数据与发送方发送数据是否一致
协议特性:
- 无连接(只要知道对端地址即可直接发送)
- 不可靠(不保证数据安全,不保证数据有序到达对端)
- 面向数据报:无连接,不可靠,无序,有最大长度限制的传输方式
注:
udp传输时,sendto发送的数据会被放到发送缓冲区,udp直接从缓冲区读取并封装头部后发送
udp传输时,接收的数据会被放到接收缓冲区,udp解析8字节头部获取数据长度,实现整条数据交付,不会出现半条或多条交付
所以在编程过程中:为了规避udp缺点
1,,不保证安全达到:需要在应用层使用tcp部分机制
2,不保证有序到达:需要在应用层进行包序管理
3,udp报文有最大长度限制:报文最大长度小于64k,因此发送大块数据时,需要在应用层进行数据分包进行发送
4,udp实现整条交付,不存在粘包问题:因此缓冲区需要足够大,能够存放整条数据
TCP协议:
协议特性:
- 面向连接:连接管理+状态管理
- 握手三次,挥手四次
tcp是一个全双工通信,两端都必须确认对方是否具有数据收发能力,因此握手两次不安全,四次没必要
fin包只能表示对方不在发送数据了,不代表对方不再接收数据,因此有可能被动关闭方还会继续发送数据,因此这种情况下就不能直接发送fin包,而是等待上层用户不在发送数据了,等调用close被动方关闭才会发送 fin,表示被动方也不再发送数据,经过双方都确认后再关闭
- 三次握手失败的处理:
服务端发送syn+ack后,如果超时等不到客户端的ack确认,会发送rst重置连接报文,释放新建套接字
- TIME_WAIT作用:
TIME_WAIT是主动关闭方在关闭连接过程中进行最后一次回复ack后进入的状态
如果被动关闭方没有收到最后一次回复,则会重传fin,若没有TIME_WAIT,主动关闭方最后一次回复(ack)则直接释放资源,此时如果客户端重新启动一个套接字刚好为之前地址信息,这个套接字可能会接收到重传的fin导致新连接也受影响,主要是保护客户端,不会使用刚关闭的套接字地址信息,从而受到上一个套接字通信遗留问题影响
TIME_WAIT等待2个msl时间(2*60s)之后,释放资源,保证能够对重传的fin进行处理,以保证本次通信的所有数据都消失在网络当中不会对新连接造成影响
- 一台主机出现大量TIME_WAIT
TIME_WAIT是套接字主动关闭连接后进入的状态,因此大量TIME_WAIT意味大量套接字关闭
解决方法:(1)减少TIME_WAIT时间 (2)使用套接字选项setsockopt(SO_REUSEADDR):地址复用(进入TIME_WAIT的地址可以直接使用,服务端关闭后可重启)
- 一台主机出现大量CLOSE_WAIT
CLOSE_WAIT是被动关闭方收到fin包进行ack回复之后进入的状态 这个状态是在等待被动关闭方的上层用户调用close/shutdown后再次发送fin包
一台主机出现大量CLOSE_WAIT意味着代码中没有调用close/shutdown关闭套接字
tcp连接保活机制:
通信两端在长时间没有数据通信的情况下,服务端会每隔一段时间向客户端发送一个保活探测数据包(要求对方进行回复),若连续多次没有收到回复,则认为连接已断开
默认7200s没有数据通信会每隔75s发送保活数据包 9次无回复则连接断开
连接断开对程序的影响:recv返回0 send会触发SIGPIPE异常
- 可靠传输:保证数据有序安全到达对端
1,面向连接,基于连接,确保通信双发都具有收发数据能力
2,协议字段中的序号和确认序号,进行包序管理,实现有序传输
3,确认应答机制:接收方针对收到的每一条数据进行确认回复(认为之前的数据都是准确有序的)
4,超时重传机制:发送数据等待超时无回复后,认为数据丢失进行重传
(1)停等协议:收到确认回复后才会发送下一条
(2)回退n步协议:从丢失的数据开始进行重新传输
(3)选择重传协议:哪一条丢失,重传哪一条
5,协议字段的校验和字段:校验数据一致性,不一致则丢弃,发送重传请求
6,过程中避免丢包
(1)发送数据过快过多导致接收方缓冲区满溢而丢包
解决方法:滑动窗口机制(依赖协议字段中窗口大小字段实现) 流量控制
每一方都有一个:接收窗口,发送窗口 (前沿-后沿)<对方窗口大小
发送窗口:前沿:起始发送序号 后沿:结束发送序号
接收窗口:前沿:起始接收序号 后沿:结束接收序号
(2)网络信号不好,导致大量丢包重传
解决方案:拥塞机制 以慢启动快增长的形式进行传输
发送方维护一个拥塞窗口,用于限制当前能发送的数据大小,而这个拥塞窗口以指数层级增长,实现网络探测,防止传输过程中网络状态突然变差继续大量发送导致的大量丢包
7,性能提升
(1)确认序号:告诉发送方确认序号之前的所有数据都已经接受成功,避免因为中间的某个确认回复丢失而导致的重传
(2)快速重传:减少超时等待时间
接收方在接受数据时,先接收到了后发的数据,则认为前边的数据有可能丢失,则连续间隔发送三条前边数据的重传请求(确认序号为丢失的数据起始序号)
发送方收到三条连续重传请求(防止延迟到达的误判),则将对应确认序号的数据重传
(3)延迟应答机制:接收到数据后,延迟确认回复
接收方接收数据后如果立即回复,上层尚未将数据取出导致滑窗大小会减小,延迟期间,上可能会将数据取出,恢复滑窗大小,保证窗口大小,保证传输吞吐量
(4)捎带应答机制:将确认回复信息放到即将要发送的数据报头中,捎带一块传输给对方,尽量减少纯报头的回复确认
总结
tcp如何实现可靠传输?
1,可靠传输:面向连接,包序管理,确认应答,超时重传,校验和
2,避免丢包:滑动窗口流量控制,拥塞机制(慢启动快增长)
3,提高性能:快速重传,延迟应答,捎带应答
udp如何实现可靠传输?
在应用层依靠tcp实现可靠传输的机制来实现
- 面向字节流 :有序可靠双向基于连接的 字节流传输,没有大小限制,以字节为单位
tcp将要发送的数据放在发送缓冲区,通信时tcp会从缓冲区取出合适大小数据(不大于mss大小)进行头部封装发送
优点:(以udp面向数据报比较)传输灵活
缺点:产生粘包问题,将许多数据当一条数据来处理
本质原因:tcp不维护数据边界
解决方法:应用层进行数据边界管理(特殊字符间隔(http:\\r\\n),数据定长,应用层头部加数据长度字段eg:http(Content-Length))
以上是关于Linux网络编程(传输层协议 )—tcp三次握手/四次挥手的主要内容,如果未能解决你的问题,请参考以下文章