urg:紧急指针标志,1 有效,0 忽略。
ack:确认序号标志,1 表示确认号有效,0表示报文中不含确认信息。忽略确认号字段。
psh:push标志,1表示带有push标志的数据,指示接收方在接受到该报文段应尽快将报文段交给应用程序,而不是在缓冲区进行排队。
rst:重置连接标志,用于重置连接,或拒绝连接请求(用于处理连接中断)
syn:同步序号,用于建立连接过程 syn = 1 ack = 0 表示该数据段没有使用稍待的域,则连接应答稍待一个确认则syn=1 ack = 1
fin:finish标志,用于释放连接 1 表示发送方已经没有数据发送了 即关闭本方数据流。
当应用程序希望通过tcp与另一个程序通讯时,他会发送一个通信请求,这个请求必须被送到一个确切的地址,当双方握手之后tcp将在两个应用之间建立一个全双工即Full duplex的请求,这个全双工的通讯将占用两个计算机之间的通信线路,知道一方或双方关闭为止.
full duplex: 当A给B发送信息的同时,B也可以给A发送信息.
各个状态的意义如下:
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT -在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;
三次握手流程
第一次握手:主机A发送位码为SYN=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;
第二次握手,主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),SYN=1,ACK=1,随机产生seq number=7654321的包;
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ACK是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ACK=1,主机B收到后确认seq值与ACK=1则连接建立成功。
为什么需要三次握手?
首次握手存在隐患-----SYN超时
首次握手存在存在SYN超时的问题,Server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认,Server不断重试直至超时,Linux默认5次,总共需要63秒断开连接.
此时即可使用SYN攻击(SYN Flood):建立大量的半状态连接,消耗CPU,内存,主机,路由器,网络资源.
针对SYN Flood的防护措施:
另外针对建立连接后,Client出现故障也有一定的防护措施-----保活机制
keepAliveTime:保活时间,用于测试连接在时间周期内是否活跃
这里提供一个动态演示的链接
https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/selective-repeat-protocol/index.html
RTT:发送一个数据包到收到对应的ack,所花费的时间
RTO:重传间隔,定时器时间,如果回复了ack定时器失效,如果没有回复,RTO定时器的时间到了就重传,RTO是通过RTT计算出来的
TCP使用滑动窗口做流量控制与乱序重排
图示两个条框即发送端与接收端的缓冲区,都统一看作“从左往右”发送数据(写入缓冲区)或接受数据(从缓冲区读取)。
LastByteWritten指上层应用最新写入缓冲区要发送字节的位置
LastByteAcked指向收到的连续最大ack的位置(从最左端到此是已发送并收到回执的位置)
LastByteSent指向已发送的最后一个字节位置
LastByteRead指上层应用已读取接收的最后一个字节位置(已发送ACK回执)
LastByteExpected指已收到的连续最大的sequence的位置但还没发送回执
LastByteRcvd指已收到的最后一个字节的位置
还能够接受的窗口大小:AdvertisedWindow
还需要发送的窗口大小:EffectiveWindow
TCP滑窗可靠性,建立在确认重传基础上
发送方只有收到本段发送滑窗的ACK确认,才移动滑窗左边界
接收方只有在收到的数据ACK之后,才会移动滑窗左边界
接收方前面收到的数据未ACK,后面收到数据,不移动滑窗
确保发送放重传后面的数据。
滑窗大小可动态调整
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KLny5L14-1643873617976)(D:\Note\详解\计算机网络\02.assets\image-20220203142147829.png)]
挥手过程:
TCP 终止连接的四次挥手:
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进去FIN_WAIT_1状态
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1,Server进入CLOSE_WAIT状态
第三次挥手:Server发送一个FIN用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
为什么需要四次挥手才能断开连接呢?
原因:因为TCP是全双工的,所以发送方和接收方都需要FIN报文和ACK报文。即发送方和接收方各自两次挥手即可。只不过一方是被动,所以看上去像四次挥手。
为什么会有TIME_WAIT状态?
原因:
为啥出现大量CLOSE_WAIT状态的原因?
原因:
**解决方式:**检查代码(释放资源的代码)和检查配置(处理请求的线程配置)
Linux查看服务器连接数命令:
netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'
UDP报文结构
1.source port 源端口
2.destination port 目标端口
3.length 数据包长度
4.checknumber校验值
5.data数据包
UDP的特点: