目录
1.TCP的状态转换
1.1 LISTEN状态和ETABLISHED状态
编辑2.TIME_WAIT 和 CLOSE_WAIT
2.滑动窗口
1.TCP的状态转换
我们通过上图可以看到TCP状态转换的详细过程.在实际开发的过程中,我们不需要了解的这么细致.为了方便大家的理解,我挑几个主要的状态来给大家聊一下
1.1 LISTEN状态和ETABLISHED状态
我们可以通过命令行 netstat -ano | findstr 10111
表示查询端口号为10111的服务器状态 注:此时我们仅仅是将服务器启动了,并没有做别的操作
可以看到有一个LISTENING的服务器状态(Windows操作系统上是这样,但是到了Linux操作系统上就是我们说的LISTEN状态了),该状态的意思是服务器已经启动就绪(即创建好了SeverSocket对象,并且绑定好了端口号),客户端可以给它发送请求了,这就好比开了一个饭店,早上起来把门打开,告诉路过的客人,我们这个饭店已经开门了,欢迎随时来吃饭.
接下来我们来观察一下
ESTABLISHED这个状态,这个状态的意思是已经有客户端和该服务器完成了三次握手创建链接的了
即可以向这个服务器发送请求了
我们接着输入 netstat - ano | findstr 10111 来观察一下
2.TIME_WAIT 和 CLOSE_WAIT
CLOSE_WAIT表示,在接下来的代码中需要调用close来主动发起fin 收到对方的fin之后进入这个状态.通俗易懂的说,就是加入客户端要向服务器发起fin,断开连接,服务器立马回了一个ack,并且进入到
对端给我发送了一个fin以后,我需要主动也调用close,这个时候的状态就是CLOSE_WAIT状态.属于一种被动的状态.
而TIME_WAIT则表示本端给对方发起FIN之后,对端业给我发FIN,此时本端进入TIME_WAIT.给最后一个ACK重传留有一定的时间.
即谁主动断开连接,谁进入TIME_WAIT状态.
一般情况下,不太容易观察到CLOSE_WAIT状态,待会会比较快速的关闭socket,状态就会从CLOSE_WAIT->LAST_ACK
如果发现服务器有大量的CLOSE_WAIT就意味着代码有bug,如忘记关socket
TIME_WAIT状态.更容易观察到.它存在的意义是为了防止最后一个ack丢包
2.滑动窗口
滑动窗口机制是TCP协议中很有意思的一种机制,它的作用主要是为了提升传输效率,据我们前面所讲的,TCP协议中每次传输数据都会等待对端发送一个ack报文以后才会继续重传下一份,但是这样的效率会很低,不利于我们传输大量的数据.所以前辈们设计了滑动窗口机制.主要的机制是,我们发送端可以一次发送多个数据,然后等待一份ack即可,等到了以后继续发送,这样可以将传输效率大大提高了, 我们用一张图来生动形象的描述一下滑动窗口的过程.
这就是滑动窗口,属于一种批量传输,之前我们是发送一个数据等一下ack然后在发下一条数据.,
而现在则是发送一波数据以后,统一等一波ack,把多次请求的时间统一成一份时间来等.
虽然这种方式提高了传输效率,但是TCP协议的一大特性就是可靠传输,那么滑动窗口这种特性该如何保证可靠传输呢?
我们分为两种情况来看
第一种.ack丢了,这种方式其实并不影响我们的可靠传输,只要后续有ack传过来就行,比如我们2001这份ack丢了,但是后面传来了3001这个ack,就说明3000之前的所有数据都是完整的到了接收方了,此时发送方接着发就行,
这对于可靠性没有影响,也不需要重传.
如上图所示,虽然1001和2001都丢了,但是3001顺利反馈过去了,此时发送方就明白了.我们3001前面的数据都没问题,就不需要重传了.
2.数据丢了 (这种就得重传了)
如上图锁是,我们的1001-2000丢了以后,接收方就会一直重复的发送1001这个ack,告诉我们应该要以1001作为首个字节来发送,当窗口大小到了极限时,就会发送1001,此时会受到7001,就会告诉我们7001之前的数据都没问题,所以可以继续发送了.