最近想写个socket池,就是从池内取出一个socket供使用。然后用完了就DisconnetEx并指定TF_ REUSE_SOCKET,最后把这个socket放回池内供下次使用。如果单单供AcceptEx使用的话,好像没什么问题。但是如果供ConnectEx使用,DisconnetEx断开后并使用同一个socket连接同一个地址端口的时候,会报WSAGetLastError码是52,错误内容是 由于网络上有重名,没有连接。
我的想法是有没有办法可以把socket重置后重用它。无论connect accept都能够重用它。
关于winsock编程socket的重用问题
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
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的时间就好了
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报