https://juejin.cn/post/7045059219216662564
主要要记住TCP的各个状态和流程
1.握手过程中,TCP头部主要用到的部分有
序列号:解决网络包乱序
确认号:解决网络包丢失
标志位:(SYN, ACK, FIN, RST)不同标志位表示着不同含义
SYN为1时,表示希望创建连接;ACK为1时,确认号字段有效;
FIN为1时,表示希望断开连接;RST为1时,表示TCP连接出现异常,需要断开;
三次握手
一
最开始,服务端和客户端都处于CLOSE状态;然后服务端主动监听某个端口,处于 "LISTEN" 状态。
开始连接是先由客户端发起请求,随机生成一个 client_isn(客户端序列号),把标志位SYN置为1,
表示请求建立连接,将报文发送给服务端,客户端便进入了 "SYN_SEND" 状态。
二
服务端接收到请求后,自己也初始化一个新序列号,一般称为server_isn; 并且在接收到报文的确认号里填上 client_isn + 1
并且把SYN和ACK都置为1.把该报文发送给客户端,服务端的状态变成 "SYN_REVD" 状态
三
客户接收到报文后,要告诉服务端,会在确认号上对server_isn + 1,并且将ACK置为1.
发送给服务端后,客户端状态为 "ESTABLISHED" 状态;服务端接收到客户端报文后,也进入了 "ESTABLISHED"状态。
知识点总结
1.两次握手只能保证客户端序列号被服务端成功接收,无法保证服务端信号是否被客户端接收。
2.序列号随机为了安全性,避免别人模拟造成网络攻击;随机性不同的位有用时间戳加其他id位之类的雪花算法,忘记了。
3.网络不可靠,中途丢包了怎么办
a.假如第一个包丢了,客户端发起连接的SYN请求丢了,客户端发出后迟迟收不到服务端ACK包,会周期性超时重传
b.假设第二个包丢了,服务端发送的SYN+ACK包丢了,服务端就迟迟收不到客户端的ACK包,也会周期性超时重传。
c.假设第三个包丢了,客户端进入了 "ESTABLISHED",此时服务端有3种情况
i.若客户端与服务端都还没发送数据,服务端会超时重传SYN+ACK包给客户端。
ii.若客户端将ACK + Data发送给服务端,那服务端就进入 "ESTABLISHED" 状态,并且接收客户端的Data数据。
iii.如果此时服务端要先发送数据了,但发送不了,服务端会一直周期性超时重传SYN + ACK
四次挥手(需要4次的主要原因:客户端第一次发送FIN之后,只表示客户不再发送数据给服务端;但它还具体数据接收能力)
一
假如客户端打算关闭连接,会发送FIN标志位的报文给服务端,发送完之后客户端进入了"FIN_WAIT_1"状态。
二
服务端接收到FIN报文后,回复ACK给客户端,服务端此时进入"CLOSE_WAIT"状态
三
客户端接收到服务端的ACK报文后,就进入了"FIN_WAIT_2"状态;
这时可能服务端还有数据要发给客户端,等发送完了,就发送FIN给客户端,自己就进入了"TIME_WAIT"状态。
四
客户端接收到服务端FIN报文后,回应ACK报文,自己就进入了"TIME_WAIT"状态;
服务端接收到客户端ACK报文后,服务端进入了"CLOSE"状态;
客户端在TIME_WAIT等到2MSL,也进入了"CLOSE"状态
知识点总结
1.TIME_WAIT的作用:
a.保证最后的ACK让对方接收到,如果没接收到会超时重发
b.在确保创建下一个新连接时,先前网络中残余数据都丢失(抛弃),不会引发错乱数据
2.2MSL是多久:它是最大报文生存时间,不同系统默认不一样,windows为2分钟,linux 60秒。
linux下查看这个值目录为 'cat /proc/sys/net/ipv4/tcp_fin_timeout'
可根据自己的需求去合理设置它的资源回收时间,不然它的状态过多,会占用内存资源。