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