我们通过一个例子来说说TCP连接的建立与断开:

       在这个例子中,客户端发起连接,发送请求,服务端响应请求,然后客户端主动关闭连接。

wKiom1c5yNShcxizAAB3OS4j73U590.png

建立连接的过程:

       1.客户端发出段1,SYN表示连接请求,如图中所示,序号是1000,每发送一个数据字节,这个序号就要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况,SYN和FIN位也要占一个序号,从第一段可以看出,这次发送的数据是0(即没有发送数据),但是由于SYN要占一位,因此下次发送数据要从1001开始。mss表示最大段尺寸,如果一个段太大,封装成帧后,超过了链路层的最大帧长度,就要在IP层分片,所以客户端要声明自己的最大段尺寸,建议服务器发过来的段不要超过这个长度;

       2.服务器发出段2,也带有SYN位,同时置ACK位表示确认,确认序号1001,表示确认1000及以前的段都正确接收,也就是答应了客户端的连接请求,同时也给客户端发送一个连接请求,也声明了自己的最大段尺寸。

       3.客户端发出段3,对服务器的连接请求进行应答,确认序号是8001(8000+SYN);

       以上就是连接建立的过程,我们可以看到在连接建立的过程中,一共有3个段,称为“三次握手”。在建立连接的同时,双方协商了诸如双方发送序号的初始值,最大段尺寸等一些信息。

       如果一方收到对方发来的段中的端口号发现本机并没有任何进程使用这个端口号,就会发送一个包含RST的段给另一方。

接下来我们再来看数据传输的过程:

       以上图中的数据为例,我们来分析:

       1.客户端发出段4,发送的数据是20字节,发送序号从1001开始;

       2.服务器发出段5,确认序号是1021(1001+20),同时请求发送从序号1021开始的数据,服务器在应答的同时也发送了从8001开始的10字节数据;

       3.客户端发出段6,确认对端发来的从8001开始的10字节数据已收到,请求发送从8011开始的数据

       在这里我们要注意,在数据传输过程中,ACK和确认序号是非常重要的,应用层交给TCP协议的数据会暂存在TCP层的发送缓冲区中,在发出数据包之后,只有收到了对方的ACK确认应答,才知道该数据已到达对端,可以从发送缓冲区释放掉了,如果因为某些故障丢掉了数据报或者对方发回的ACK段没收到,经过等待超时后,TCP协议自动将发送缓冲区中的数据包重发。


关闭连接的过程:

       1.客户端发出段7,FIN位表示关闭连接的请求;

       2.服务器发出段8,应答客户端的关闭连接的请求;

       3.服务器发出段9,同时也向客户端发出关闭连接请求;

       4.客户端发出段10,应答服务器的关闭连接的请求;

      

       从上面可以看到,关闭连接需要4段,服务器的应答和关闭连接请求不在一个段上,这样做的目的是有连接半关闭的情况,什么意思呢?就是在这种情况下,客户端就不能再向服务端发送数据包了,服务器还可以发送数据包给客户端,直到服务器也关闭连接为止。

       我们以上的例子只描述了最简单的一问一答时的情况,实际的TCP数据传输过程可以收发很多数据段,事实上,TCP协议为应用层提供了全双工的服务,双方都可以主动或者同时给对端发送数据包。