( 该图由AI制作 )
目录
数据收发完成后协议栈要执行的操作
数据发送完毕后断开连接
删除套接字
数据收发操作小结
第一步是创建套接字
然后
客户端会向服务器发起连接操作
数据收发阶段
执行断开操作
数据收发完成后协议栈要执行的操作
数据发送完毕后断开连接
前面讲了:创建套接字到连接、收发数据、断开连接、今天讲:删除套接字
服务器一方的应用程序会调用
Socket
库的
close
程序
。
然后
,
服务器的协议栈会生成包含断开信息
的
TCP
头部
,
具体来说就是将控制位中的
FIN
比特设为
1
。
接下来
,
协议
栈会委托
IP
模块向客户端发送数据
(
图
①
)
接下来轮到客户端了
。
当收到服务器发来的
FIN
为
1
的
TCP
头部时
,
客户端的协议栈会将自己的套接字标记为进入断开操作状态
。
然后
,
为
了告知服务器已收到
FIN
为
1
的包
,
客户端会向服务器返回一个
ACK
号
(
图
②
)。
这些操作完成后
,
协议栈就可以等待应用程序来取数据了
客户端调用read和close
这时客户端的协议栈也会和服务器一样
,
生成一个
FIN
比特为
1
的
TCP
包
,
然后
委托
IP
模块发送给服务器
(
图
③
)。
一段时间之后
,
服务器就会返回
ACK
号
(
图
④
)。
到这里
,
客户端和服务器的通信就全部结束了
删除套接字
和服务器的通信结束之后
,
用来通信的套接字也就不会再使用了
套接字并不会立即被删除
会等待一段时间之后再被删除(为了防止误操作)
至于具体等待多长时间
,
这和包重传的操作方式有关
协议中对于这个等待时间没有明确的规定
,
一般来说会等待几分钟之后再删除套接字
数据收发操作小结
第一步是创建套接字
服务器一方的应用程序在启动时就会创建好套接字并进入等待连接的状态
。
客户端则一般是
在用户触发特定动作
,
需要访问服务器的时候创建套接字
。
在这个阶段
,
还没有开始传输网络包
然后
客户端会向服务器发起连接操作
客户端,生成一个
SYN 为 1
的 TCP 包,发送给服务器(图①)
(TCP 包头部还包含了客户端向服务器发送数据时使用的初始序号,以及服务器向客户端发送数据时需要用到的窗口大小)
到达服务器之后
服务器会返回一个
SYN
为
1 的 TCP 包(图②)
(和图①一样,这个包的头部中也包含了序号和窗口大小,此外还包含表示确认已收到包①的ACK 号)
当这个包到达客户端时
客户端会向服务器返回一个包含表示确认的
ACK
号的
TCP
包(图③)
连接操作就完成了,双方进入数据收发阶段
数据收发阶段
客户端会向服务器发送请求消息
TCP
会将请求消息切分成一定大
小的块
,
并在每一块前面加上
TCP
头部
,
然后发送给服务器
(
图
④)
(TCP 头部中包含序号,它表示当前发送的是第几个字节的数据)
当服务器收到数据时
会向客户端返回
ACK
号(图⑤)
在最初的阶段
,
服务器只是不断接收数据
,
随着数据收发的进行
,数据不断传递给应用程序,接收缓冲区就会被逐步释放
这时,服务器需要将新的窗口大小告知客户端。当服务器收到客户端的请求消息后,会向客户端返回响应消息,这个过程和刚才的过程正好相反(图⑥⑦)。
执行断开操作
服务器会先发起断开过程(在
HTTP1.1
中,有可能是客户端发起断开过程。)
服务器先发送一个
FIN
为
1
的
TCP
包
(
图
⑧
)
然后客户端返回一
个表示确认收到的
ACK
号
(
图
⑨
)
接下来
,
双方还会交换一组方向相
反的
FIN
为
1
的
TCP
包
(
图
⑩
)
和包含
ACK
号的
TCP
包
(图11)。
最后
,
在等待一段时间后
,
套接字会被删除