肥矮丑 2024-10-01 22:58 采纳率: 100%
浏览 9
已结题

关于winsock编程socket的重用问题

最近想写个socket池,就是从池内取出一个socket供使用。然后用完了就DisconnetEx并指定TF_ REUSE_SOCKET,最后把这个socket放回池内供下次使用。如果单单供AcceptEx使用的话,好像没什么问题。但是如果供ConnectEx使用,DisconnetEx断开后并使用同一个socket连接同一个地址端口的时候,会报WSAGetLastError码是52,错误内容是 由于网络上有重名,没有连接。
我的想法是有没有办法可以把socket重置后重用它。无论connect accept都能够重用它。

  • 写回答

1条回答 默认 最新

  • 肥矮丑 2024-10-02 02:31
    关注

    已经找到问题所在了,如下解释:
    如果使用 TF_REUSE_SOCKET 标志调用 DisconnectEx 函数,则指定的套接字将返回到未连接但仍绑定的状态。 在这种情况下,套接字的句柄可以传递给 ConnectEx 函数的 s 参数。

    在 TCP 可以释放已关闭的连接并重用其资源之前必须经过的时间间隔称为TIME_WAIT状态或 2MSL 状态。 在此期间,与建立新连接相比,重新打开连接对客户端和服务器的成本要低得多。

    TIME_WAIT行为在 RFC 793 中指定,该行为要求 TCP 在至少等于网络 MSL) 最大段生存期 (两倍的间隔内保持关闭连接。 释放连接后,其套接字对和用于套接字的内部资源可用于支持另一个连接。

    Windows TCP 在连接关闭后还原为TIME_WAIT状态。 处于TIME_WAIT状态时,不能重复使用套接字对。 可以通过修改以下 DWORD 注册表设置来配置TIME_WAIT周期,该 DWORD 注册表设置表示以秒为单位的TIME_WAIT周期。

    \ HKEY_LOCAL_MACHINE系统\CurrentControlSet\服务\TCPIP\参数\TcpTimedWaitDelay

    默认情况下,MSL 定义为 120 秒。 TcpTimedWaitDelay 注册表设置默认为值 240 秒,表示 120 秒或 4 分钟的最大段生存期的 2 倍。 但是,可以使用此项来自定义间隔。

    通过减小此项的值,TCP 可以更快地释放已关闭的连接,为新连接提供更多资源。 但是,如果该值过低,TCP 可能会在连接完成之前释放连接资源,从而要求服务器使用其他资源来重新建立连接。

    可以将此注册表设置设置为 0 到 300 秒。

    比较常规化的答案,linux也是这个答案: 也就是每个socket无论是reuse还是closesocket,socket连接断开后,都要等待2MSL的时间,默认都是120秒(MSL),2MSL=(2*120)=240秒。

    也就是当我从池中取出socket用来ConnectEx成功后,再用DisconnectEx断开连接之后,我再Sleep(240000)后,再使用它重新ConnectEx就能正常了。也就是说,如果想快速重用socket,在于如何缩短MSL的时间就好了

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 10月10日
  • 已采纳回答 10月2日
  • 创建了问题 10月1日