Network
- Wifi
- Bluetooth
- NFC
Model
Protocol
Format
Region
LAN
Private
Hardware
NIC
Physical Layer(物理层)
Data Link Layer(链路层)
MAC
ARP
Network Layer(网络层)
IP
Address
Subnet
Gateway
Route
Transport Layer(传输层)
- TCP是面向连接的,UDP是面向非连接的
- TCP是可靠的,UDP是不可靠的
- TCP面向字节流的,UDP是面向数据报的
- TCP只支持点对点通信,UDP支持一对一,一对多,多对多
- TCP有发送缓冲区,UDP没有发送缓冲区
TCP
Connection
最大报文存活时间:MSL
连接重置标志:RST(代表通信异常比如网络不可达或者连接已关闭时需要关闭自己这边的连接)
连接重置提示: connect reset by peer
三次握手的流程
- 第1次:客户端发送和服务端接收
SYN
- 客户端状态变化:
CLOSED
变为SYN_SENT
- 服务端状态变化:
LISTEN
变为SYN_RCVD
- 作用:客户端发送SYN申请建立通向服务端的连接通道
- 客户端状态变化:
- 第2次:服务端发送和客户端接收
ACK
和SYN
- 客户端状态变化:
SYN_SENT
变为ESTABLISHED
- 服务端状态变化:无
- 作用:服务端发送ACK同意建立连接
- 作用:服务端发送SYN申请建立通向客户端的连接通道
- 作用:客户端收到了ACK证明服务端的接收通道和发送通道没有问题
- 客户端状态变化:
- 第3次:客户端发送和服务端接收
ACK
- 客户端状态变化:无
- 服务端状态变化:
SYN_RCVD
变为ESTABLISHED
- 作用:客户端发送ACK同意建立连接
- 作用:服务端收到ACK了证明客户端的接收通道和发送通道没有问题
ps:TCP是全双工的,即客户端和服务端可以在同一时刻都发送数据
ps:所以需要两条通道,两条通道的数据互不干扰
ps:即客户端的发送和服务端的接收是一条通道
ps:即服务端的发送和客户端的接收是另一条通道
ps:所以客户端和服务端都需要向对方发送SYN申请建立通向对方的连接通道
客户端状态变化
CLOSED
:处于已关闭的状态SYN_SENT
:客户端已经发送了SYNESTABLISHED
:处于已连接的状态
服务端状态变化
LISTEN
:处于已监听的状态SYN_RCVD
:服务端已经收到了SYNESTABLISHED
:处于已连接的状态
四次挥手的流程
- 第1次:客户端发送和服务端接收
FIN
- 客户端状态变化:
ESTABLISHED
变为FIN_WAIT_1
- 服务端状态变化:
ESTABLISHED
变为CLOSE_WAIT
- 作用:客户端申请关闭连接客户端的发送端和服务端的接收端的通道
- 客户端状态变化:
- 第2次:服务端发送和客户端接收
ACK
- 客户端状态变化:
FIN_WAIT_1
变为FIN_WAIT_2
- 服务端状态变化:无
- 作用:服务端同意关闭连接客户端的发送端和服务端的接收端的通道
- 客户端状态变化:
- 第3次:服务端发送和客户端接收
FIN
- 客户端状态变化:
FIN_WAIT_2
变为TIME_WAIT
- 服务端状态变化:
CLOSE_WAIT
变为LAST_ACK
- 作用:服务端申请关闭连接服务端的发送端和客户端的接收端的通道
- 客户端状态变化:
- 第3次:客户端发送和服务端接收
ACK
- 客户端状态变化:
TIME_WAIT
变为CLOSED
- 服务端状态变化:
LAST_ACK
变为CLOSED
- 作用:客户端同意关闭连接服务端的发送端和客户端的接收端的通道
- 客户端状态变化:
ps:TCP是全双工的,即客户端和服务端可以在同一时刻都发送数据
ps:所以需要两条通道,两条通道的数据互不干扰
ps:即客户端的发送和服务端的接收是一条通道
ps:即服务端的发送和客户端的接收是另一条通道
ps:所以客户端和服务端都需要向对方发送FIN申请关闭通向对方的连接通道
客户端状态变化
ESTABLISHED
:处于已连接的状态FIN_WAIT_1
:客户端发送了FIN并等待ACkFIN_WAIT_2
:客户端收到了对客户端的FIN的ACKTIME_WAIT
:客户端收到了服务端的FIN并发送了ACKCLOSED
:处于已关闭的状态
服务端状态变化
ESTABLISHED
:处于已连接的状态CLOSE_WAIT
:服务端收到了客户端的FIN并发送了ACKLAST_ACK
:服务端发送了FIN并等待ACkCLOSED
:处于已关闭的状态
为什么需要三次握手
- 假设不需要第三次握手,当第二次握手的ACK丢失时
- 客户端会因为没有收到ACK从而认为不可连接并放弃了连接
- 服务端会因为不需要第三次握手的ACK从而分配连接资源并等待客户端的数据
- 但客户端因为放弃了连接从而不会发送数据
- 这会导致服务端进行无效的等待直到读写超时后关闭从而占用和浪费了连接资源
为什么需要四次挥手
- 假设不需要第四次挥手,当第三次挥手的FIN丢失时
- 客户端会因为没有收到FIN从而无法关闭客户端的接收通道
- 服务端会因为不需要第四次挥手的ACK从而不会重发丢失的FIN
- 这会导致客户端无法关闭客户端的接收通道从而一直占用连接资源
为什么第二次挥手发送ACK的时候不同时发送FIN
- 第二次挥手发送ACK的时候不同时发送FIN
- 是因为服务端可能还有数据要发送给客户端
- 所以服务端不能发送FIN来关闭连接服务端的发送端和客户端的接收端的通道
为什么第四次挥手后客户端需要等待2MSL
- 主要作用
- 2MSL的作用是等待网络中的报文消失,避免服务端重发的FIN活到同一个端口下一次连接建立时影响连接的建立
- 次要作用
- 确认服务端收到了最后的ACK,这期间没有重新收到FIN则可以基本上认为服务端收到了最后的ACK
服务端的FIN超时重发时间说明
- 超时重发时间为大于
2 * MSL = MSL + MSL
- 其中一个MSL是服务端的FIN发送到客户端所能消耗的最大时间
- 另一个MSL是客户端的ACK发送到服务端所能消耗的最大时间
- 超时重发时间要大于
2MSL
说明收不到ACK了 - 所以超时重发时间要大于
2MSL
客户端需要等待2MSL的证明
- 假设服务端在x时刻发送了FIN,客户端在y时刻发送了ACK
- 则
y <= x + MSL
,因为如果y > x + MSL
后客户端就收不到服务端的FIN并发送ACK了 - 假设服务端在z时刻重发了FIN
- 则
z - x > 2MSL
,因为超时重发时间要大于2MSL
- 假设客户端等待的结束时间为t
- 则
t > z + MSL
,这样重发的FIN也会在网络中消失从而避免影响下一次的连接 - 因为
z - x > 2MSL
,即z > x + 2MSL
- 所以
t > z + MSL > (x + 2MSL) + MSL = x + 3MSL
- 所以客户端的超时等待时间为
t - y > (x + 3MSL) - (x + MSL) = 2MSL
- 所以客户端的超时等待时间取最小值时为
2MSL
为什么客户端需要TIME_WAIT状态
- 因为服务端重发的FIN活到同一个端口下一次连接建立时会影响连接的建立
- 所以需要在TIME_WAIT状态下等待2MSL的时间直到FIN的影响消失
- 如果不能跳过TIME_WAIT状态直接进入CLOSED状态
为什么服务端需要CLOSE_WAIT状态
- 因为服务端可能还有数据要发送给客户端时只能发送ACK不能直接发送FIN
- 所以需要CLOSE_WAIT来标记服务端的FIN还没发送
- 所以不能跳过CLOSE_WAIT状态直接进入LAST_ACK状态
出现了大量的TIME_WAIT和CLOSE_WAIT有什么问题
- 服务器出现了大量的TIME_WAIT
- 业务场景:服务器作为客户端(比如爬虫和请求第三方服务时)
- 出现原因:频繁地建立和关闭连接时客户端侧会出现大量的TIME_WAIT
- 解决办法:修改tcp的控制参数
- 服务器出现了大量的CLOSE_WAIT
- 业务场景:服务器作为服务端
- 出现原因:客户端申请关闭连接时服务端没有检测到或者忽略了(代码bug)
- 解决办法:需要修复代码bug
Reliability
Transmission
应用层:消息(message)
传输层:TCP报文段(segment)、UDP数据报(datagram)
网络层:数据包(packet)
链路层:帧(frame)
物理层:流(bit)