以下材料用于提供关闭套接字和关闭套接字连接所述主题作为澄清。 区分关闭套接字连接和关闭套接字之间的区别非常重要。
关闭套接字连接涉及在两个端点之间交换协议消息,此后称为关闭序列。 定义了两类通用的关闭序列:优雅和流产(也称为硬)。 在正常关闭序列中,可以在关闭连接之前发送已排队但尚未传输的任何数据。 在中断关闭时,任何未发送的数据都将丢失。 关闭序列(正常或中止)的发生也可用于向关联的应用程序提供FD_CLOSE指示,表示正在关闭。
另一方面,关闭套接字会导致套接字句柄被释放,因此应用程序无法再以任何方式引用或使用套接字。
在Windows套接字中,shutdown函数和WSASendDisconnect函数都可用于启动关闭序列,而closesocket函数用于释放套接字句柄并释放任何相关资源。 然而,由于closesocket函数隐含地导致如果尚未发生关闭序列,则会产生一些混淆。 实际上,依赖于此功能并使用closesocket来启动关闭序列并释放套接字句柄已成为一种相当常见的编程习惯。
为了方便这种用法,套接字接口通过套接字选项机制提供控件,允许程序员指示隐式关闭序列是正常还是中止,以及closesocket函数是否应该延迟(不是立即完成) 以便有时间完成正常的关闭序列。 这些重要的区别以及以这种方式使用closesocket的后果仍然没有被广泛理解。
通过为套接字选项SO_LINGER和SO_DONTLINGER建立适当的值,可以使用closesocket函数获得以下类型的行为:
- 中止关机序列,从closesocket立即返回。
- 正常关闭,延迟返回,直到关闭序列完成或经过指定的时间间隔。 如果时间间隔在正常关闭序列完成之前到期,则会发生中止关闭序列,并返回closesocket。
- 正常关机,立即返回 - 允许关机序列在后台完成。 虽然这是默认行为,但应用程序无法知道正常关闭序列何时(或是否)实际完成。
在SOL_SOCKET套接字选项和逗留结构的参考部分中更详细地讨论了SO_LINGER和SO_DONTLINGER套接字选项的使用以及相关的逗留结构。
可用于最小化连接拆除期间发生问题的机会的一种技术是避免依赖于由closesocket启动的隐式关闭。 而是使用两个显式关闭函数之一,shutdown或WSASendDisconnect。 这反过来导致对等应用程序接收FD_CLOSE指示,指示已经接收到所有未决数据。 为了说明这一点,下表显示了应用程序的客户端和服务器组件将调用的函数,其中客户端负责启动正常关闭。
客户端 | 服务端 |
---|---|
(1) 调用shutdown(s,SD_SEND)以指示会话结束,并且该客户端没有更多数据要发送。 | |
(2)接收FD_CLOSE,表示正在进行正常关闭并且已收到所有数据。 | |
(3) 发送任何剩余的响应数据。 | |
(仅限本地计时重要性)获取FD_READ并调用recv以获取服务器发送的任何响应数据。 | (4)调用shutdown(s,SD_SEND)表示服务器没有更多数据要发送。 |
(5)接收FD_CLOSE指示。 | (仅限本地计时)调用closesocket。 |
(6) 调用 closesocket. |