完整的TCP连接详解
TCP的连接分为连接建立、数据传送、连接终止三个阶段。
一、连接建立
1、服务器首先要先创建TCP套接字,然后将需要的端口号和ip地址与这个套接字绑定在一起,最后调用listen函数把这个套接字转换成一个监听套接字。这样服务器就可以接受外来的连接。
2、客户端通过调用connect来发起连接。这时候客户就会发送一个SYN(分节。没有携带什么数据,有ip首部、tcp首部。客户用来告诉服务器我客户要发送的数据一定会带上这些东西)
3、服务器接受到客户的SYN后必须要让客户知道他已经收到了,于是服务器就发送给客户一个ACK(用来确认。如果SYN里面的序列号是J,那么ACK就是J加上1。其实就是让客户知道我服务器收到了SYN。并且这个SYN确实你发送的,因为我发送的ACK就是在你的SYN上加1。)。同时服务器也要发送一个SYN(分节。有ip首部、tcp首部。服务器用来告诉客户我服务器要发送的数据一定会带上这些东西)。
4、客户也必须确认服务器的SYN,于是也要发送一个ACK回去。(这时候通信两端的序列号都增加了1,至于什么是序列号,下次有机会再讨论)
二、数据传送
上面已经建立起了连接。建立好连接后客户和服务器就可以进行数据的传送。上面有提到,这时候通信两端的序列号都增加了1。为了好描述,我们假设最开始通信两端的序列号为0,那么连接建立起来后,两端的序列号就为1。
1、客户发送第一个携带有效数据的包。其中序列号为1,确认号也为1,有效数据的长度为a(比如,你要跟你朋友说“你好”,有效数据就是“你好”)。
2、服务端发送一个包来确认客户端发来的数据,需要注意的是,确认号的值增加了a(a是客户发来的有效数据长度),变为a+1,简单来说,服务端以此来告知客户端端,目前为止,我总共收到了a字节的数据,服务端的序列号保持为1不变。
3、服务端还发送一个包,这个包标志着服务端返回客户端请求的开始,序列号依然为1,因为服务端在该包之前返回的包中都不带有有效数据,该包带有b字节的有效数据。
4、由于上个数据包的发送,TCP客户端的序列号增长至a+1,从服务端接收了a字节的数据,客户端的确认号由1增长至a+1。
序列号为当前端成功发送的数据位数,确认号为当前端成功接收的数据位数,SYN标志位和FIN标志位也要占1位
三、连接终止
1、某个进程首先调用close,我们称之为执行主动关闭。改端的TCP于是发送一个FIN(表示我要关闭了)
2、接收到这个FIN的这一端执行被动关闭。接受到后,执行被动关闭的一端发送ACK给执行主动关闭的一端(确认)
3、然后执行被动关闭的一端调用close关闭它的套接字,这时候,它也要发送一个FIN给执行主动关闭的一端。
4、执行主动关闭的一端接受到后,它发送ACK给执行被动关闭的一端(确认)
为什么不用客户和服务器来描述?因为客户和服务器都有可能发起关闭请求,为了严谨,所有用执行主动关闭的一端和执行被动关闭的一端来描述