1.TCP状态

1.LISTEN
服务器特有状态
当服务器开启,socket关联好端口号后:TCP的状态就是LISTENING(Windows是LISTENING,Linux是LISTEN)


2.ESTABILSHED(estabilshed)
服务器和客户端都会涉及到。
服务器开启,客户端也开启后:这个状态表示连接已经建立完成,接下来就可以进行网络通信了。

当前服务器和客户端在同一台主机上,所以都能看到。
3.CLOSE_WAIT
CLOSE_WAIT是等待调用close方法。
断开连接的时候,先收到FIN的一方,会先进入的状态。
一收到FIN,立即进入CLOSE_WAIT这个状态。当这一方也向对端发出FIN后,结束这个状态。
4.TIME_WAIT
主动断开的一方,在收到对方的FIN后进入的状态TIME_WAIT。
作用:等待一定时间,处理"最后一个ACK丢包"这样的情况

最后一个ACK如果丢包,接收方收不到ACK,就会重传FIN。
TIME_WAIT会等待一段时间,时间到了之后,也没有收到对面重传的FIN,就视为对方已经收到最后一个ACK,此时才能安全的释放TCP连接。
等待的时间限制:TIEM_WAIT等待2MSL(Maximum Segment Lifetime报文段最长生存时间),MSL默认值为1min。
MSL是操作系统中定义的一个"常量",可以指定。
2.TCP滑动窗口机制


滑动窗口:批量传输一组数据,发完一组后再等这一组的确认应答,窗口向后滑动继续发下一批数据。窗口越大,说明批量传输的数据越多,整体的传输效率就越高。
1.为啥要有滑动窗口机制?
因为确认应答、超时等待、连接管理这些机制为了确保可靠性,牺牲了一些效率。滑动窗口就是为了提高效率。
2.滑动窗口中丢包
(1.)ACK丢失
不需要做任何处理。
为啥ACK丢失不需要做任何处理?
要知道TCP的ACK是"累计确认",即后面的ACK可以顶替前面丢失的ACK。
比如下图中3001、4001的ACK都丢失,但最后主机A收到6001,6001就表示主机B告诉主机A:你发的1~6000的数据我全收到了。
所以不用任何处理。

当最后一个ACK丢失时:
(2.)数据丢失

掉1个:
场景:滑动窗口传输,1001~2000 这一段数据报文丢。
主机 A 一次性连续发送多段数据:1~1000、1001~2000、2001~3000、3001~4000......
-
主机 B 成功收到 1~1000,回复 ACK 下一个是 1001。
-
1001~2000的数据包在路上丢失,主机 B 收不到这一段。
-
但是后面 2001~3000、3001~4000、4001~5000 这些报文陆续到达 B。
因为 B 缺少 1001~2000 这段,不能确认后面的字节,所以每收到一个后续数据包,都会重复回复同一个 ACK:下一个是 1001。
- 主机 A 收到3 次相同的重复 ACK(三次冗余 ACK),触发快速重传:
不用等超时计时器到期,直接立刻重传丢失的1001~2000报文段。
- 当 B 收到重传的 1001~2000 之后,后续数据就可以正常累积确认,回复更大序号的 ACK(下一个是 7001、8001......)
据就可以正常累积确认,回复更大序号的 ACK(下一个是 7001、8001......)
这就是滑动窗口的快速重传机制
(3.)滑动窗口中,如果最后一个ACK丢了,那怎么办?
如果是最后一个ACK,那么此时发送速度就降低了,此时就不是快速重传了,就交给超时重传了。等待一定超时时间,就会重传。
(4.)快速重传和超时重传
快速重传:如果数据发的很快,这个时候构成滑动窗口,按照快速重传的机制。
超时重传:如果数据发的很慢,这种情况下无法构成滑动窗口,按照超时重传的机制。
3.TCP流量控制机制
流量控制:对滑动窗口大小进行控制
根据接收方的处理能力,来反向限制发送方的发送速度(滑动窗口)
1.接收方的处理能力
接收缓冲区剩余空间的大小
2.如何通知发送方,限制发送方的发送速度
把接受缓冲区剩余空间大小的值,通过ACK通知发送方。这个值就在TCP报头的"16位窗口大小"

发送方按照收到的ACK里的16位窗口大小的值来决定下一轮滑动窗口的大小。
16位窗口大小的值最大是多少?
选项里有一个"窗口扩展因子",16位窗口大小的值<<窗口扩展因子=16位窗口大小的最大值。
例如窗口扩展因子=2
那么16位窗口大小的最大值:64KB*4=256KB。
3.窗口探测包
如果接收缓冲区已经满了,此时发送方就要暂停发送。暂停发送后无法触发接收方的ACK,等缓冲区有空间了,就无法通知给发送方。

窗口探测包就可以解决这个问题。
如果接收方缓冲区已经满了,就会将窗口大小置为0------》发送方收到这个端口之后,就不再发送数据,但是会定期发送一个窗口探测数据包,使接收端把窗口大小告诉发送端。