TCP
三次握手和四次握手
画图描述
- 图
- https://blog.csdn.net/ZWE7616175/article/details/80432486
ack和seq的值
- SYN seq=x
- ACK=x+1
未就绪队列(SYN队列)
- 发过来的SYN,如果ACCEPT队列未满则放入SYN队列,并返回SYN+ACK
- 如果发来ACK时,ACCEPT队列已满了,丢弃ACK,对端重发ACK
- 如果SYN队列中SYN_REVD状态超时ACCEPT队列仍未空,则丢弃该连接
就绪队列(ACCEPT队列)
- 应用程序通过accept取走连接
三次挥手和四次握手的原因
三次握手
三次的原因:避免服务端传输问题,导致客户端一直重传,然后服务端建立大量的无效链接
第二个SYN的作用
- 如果第一个SYN阻塞了,客户端又超时重发了一个SYN。这时候之前的阻塞的SYN也到达了服务端。然而其实这个被阻塞的SYN已经无效了。如果正常返回则会监听无用的请求。可以发送一个SYN询问客户端之前的请求是否正确
服务端无法立刻建立连接
- 返回RST报文表示重置
四次挥手
- ACK和FIN分开,因为FIN前可能还有内容要发送
进入TIME_WAIT后等待2MSL后无回复则变成CLOSED
- MSL(Maximum Segment Lifetime)保文最大生存时间:超过这个时间的报文将被抛弃
- RFC793规定MSL为两分钟,实际应用常用30s、1min、2min等
- 为什么是2MSL:怕对方ACK包没收到,对方超时发来FIN包,来回最大时间是2MSL
TIME_WAIT状态存在的原因
1.可靠地实现了TCP全双工连接的终止
- 维持该连接的状态以便重发丢死的ACK
2.使旧的数据包在网络中因过期而消失
- 一条TCP连接由四元组(ip,port)作为唯一标识。如果关闭连接后迅速以同样的四元祖建立新连接,TCP协议栈无法区分新连接,可能被当成正常数据接受并上传至应用层。
网络中出现大量TIME_WAIT状态的危害
- socket关闭时TIME_WAIT状态保持1-4分钟(视实际的MSL而定)
- 快速打开关闭大量连接时会积累大量socket。而本地端口数量有限,很难再建立新的对外连接
如何消除
- 1.改为长连接。代价较大,长连接太多会导致服务器性能问题
2.客户端机器打开tcp_tw_recycle和tcp_timestamps选项
- tcp_tw_recycle:开启TCP连接中TIME_WAIT sockets的快速回收
3.客户端机器打开tcp_tw_reuse和tcp_timestamps
- tcp_tw_reuse:允许TIME_WAIT sockets重新用于新的TCP连接
4.客户端程序中设置socket的SO_LONGER选项
5.客户端机器设置tcp_max_tw_buckets为一个很小的值
- 该值用于防止Dos攻击,不应该人工减少,甚至应该增加。
建立连接后如何保持连接(检测未断开)
1.TCP协议层的Keepalive机制
- 连接闲置一段时间后( 默认两个小时),TCP协议向对方发送一个keepalive探针包(没数据)。
- 对方收到后,如一切正常应回复ACK
- 出错则回复RST
- 没回复则重发,多次重发没回应则视作断开
2.应用层自己实现的HeartBeat心跳bao
- 客户端定时发送一个小包,告诉服务端自己还存活
拥塞控制
- 防止过多数据注入到网络中,全局性,涉及所有主机,路由器
方法
慢启动
不知道网络状态时,试探性把拥塞窗口cwnd设为1,然后逐次翻倍。达到门槛时,转为拥塞避免算法
- 门槛无规定值,为任意大值
拥塞避免算法
加法增加
- 发生拥塞时(确认超时),减半,重新启动慢启动
快重传
接受方一旦收到失效报文就发出对失效报文前一个报文的重复确认,一旦收到三个重复确认就马上重发(不要等确认超时)
- 吞吐量20%
快恢复
- 发生阻塞时不重新从1开始慢启动,而是从慢启动阀值开始加法增加
图解
流量控制
滑动窗口机制
- 发送、接收方都有缓冲区
- 发送窗口即缓冲区中允许被发送的区间
动态调整窗口大小
- 返回窗口为0,说明要等接收方的缓冲区清空才能继续接收
窗口过小
- 影响效率,发一个报文等一个ACK
窗口过大
- 网络易堵塞,容易造成接受端缓存不足溢出丢包->多次重复发送数据
考虑传输效率
Nagle算法
- 只允许网络中有一个小包,避免发送大量小包(协议头非常大)造成拥塞
实质指责为数据累积,门槛有三
- 1.缓冲区超过阀值
- 2.等待超过一定时间(一般200ms)
- 3.紧急数据发送
糊涂窗口综合症
发送端
- 产生数据慢,一产生就发送;如产生1个字节,就发送1+20(IP头)+20(TCP头)。逐字节传输产生较长时延
接受端
- 消费数据慢,每次只消费1字节,就发送确认报文并设置窗口为1字节,导致小包的发送。
解决
- 1.Nagle算法,在等ACK的时候积攒数据
- 延长ACK.从而延迟窗口通告,给时间放大接受窗口
3.Clark解决方法
- 收到数据就确认,但是宣告窗口为0
- 直到缓冲区已经空一半||有足够空间
TCP黏包
- UDP不会产生黏包,因为有边界
原因
- 1.Nagle算法造成的发送端黏包
- 2.接受端接受不及时,造成TCP缓存区存放了几段数据,却来不及分组
解决
1.关闭Nagle算法
- 关闭优化算法,降低网络发送效率
2.接受端尽可能快速地从缓冲区读取数据
- 只是减少黏包的可能性
3.发送的数据中,添加一个表示数据的开头和结尾的字符,收到消息后通过这些字符处理
- 添加发送长度
- https://www.cnblogs.com/qiaoconglovelife/p/5733247.html
头部有哪些字段?【结合谈作用!】
头部
源端口和目的端口字段
- 各两字节
- 端口是运输层和应用层的服务端口
- 运输层的复用和分用功能都要通过端口才能实现
序列字段
- 4字节
- 传输的数据流中每一个字节都编上一个序号
该字段指本报文所发送的数据的第一个字节的序号
- 如序号字段为301,携带100字节,则最后一个字节的序号为400.下一个报文从401开始
确认号字段
- 4字节
- 期望收到对方的下一个报文段的数据的第一个字节的序号
- 若确认号为N,则表明到序号N-1位置的所有数据都已正确收到
数据偏移(即首部长度)
- 指出TCP报文段的数据起始处距离TCP报文段的起始初有多远
- 以四字节为计算单位(单位32位),所以值为15时,首部字段为60字节。
保留字段
- 占6位,目前为0,暂可忽略
紧急位URG
- URG=1时,报文有紧急数据,应尽快传输
- 配合紧急指针使用,从第一个字节到紧急指针所指的字节就是紧急数据
确认位ACK
- ACK=1时确认号字段才有效
- TCP规定,连接建立后,所有传送的报文段都必须把ACK重置为1
推送位PUSH
- 接受TCP收到PSH=1的报文段,就尽快的交付应用程序,不再等整个缓存都填满了再向上交付
复位位RST
- RST=1时,TCP连接中出现严重的差错,必须释放连接,然后重新建立运输连接
同部位SYN
- SYN=1表示这个连接还活着
终止位FIN
- 用来释放一个连接
- FIN=1表明发送方的数据已经发送完毕,并要求释放传输连接
窗口字段
- 2字节
- 表示当前允许对方发送的最大数据量,单位为字节
- 如:窗口字段为1000,确认好为701,说明还有100字节的数据缓存空间(从701到1700)
校验和
- 2字节
需要加12字节的伪首部
- 32位的源IP地址
32位的目的IP地址
- 检验是否收错
8个保留字节
- 8位传输协议号(tcp是6,udp是17)
- 16位TCP报文长度
校验的计算过程
- 计算三个部分:TCP首部+TCP数据+TCP伪首部
- 都分为16bit的字节,若长度为奇数,则最后添加一个都为0的字节
- 反码相加所有的16位(进位也要累加,进位(大于16bit)则高位叠加到低位)
紧急指针字段
- 16位
- 指出本报文紧急数据共有多少个字节
选项字段
- 长度可变
- TCP最初只规定了MSS(最大报文段长度)
- 即数据字段的最大长度
填充字段
- 为了使整个首部是4字节的整数倍
如何保持可靠传输
- 1.三次握手建立连接
- 2.讲数据截断为合理的长度(按字节编号,合理分片),使数据包长度保持不变(区别于UDP)
- 3.超时重发机制(定时器超时前收不到目的端的确认报文段将重发)
- 4.对于收到的请求,给出响应(会延迟几分之一秒,可能为包的完整校验)
- 5.校验出包有错则丢弃报文段且不响应,让对方超时重发(保持首部和数据的校验和,端对端校验和)
- 6.能丢弃重复数据
7.TCP可进行流量控制,防止较快主机致使主机的缓冲区溢出
- 流量控制协议:可变大小的滑动窗口协议
8.提供拥塞控制。网络拥塞时减少数据的发送
IP地址的分类
0
2**7
27+26
27+26+2**5
27+26+25+24
协议对应端口默认端口
http
- 80
https
- 443
ftp
- 20、21
telnet
- 23
SMTP
- 25
OSI模型
应用层
- 为应用程序提供服务
- HTTP、FTP、SMTP、Telnet、DNS
表示层
- 数据格式转化、数据加密
- JPEG、MIDI
会话层
- 建立、管理和维护会话
- PFC、SQL
传输层
- 建立、管理和维护端到端的连接
- TCP、UDP
网络层
- IP选址及路由选择
- IP、ARP、IPX
数据链路层
- 提供介质访问和链路管理
- HDLC、VLAN
物理层
- 物理层
- IEEE802.3