Winsock 错误 10054 (WSAECONNRESET) 与 UDP 到/来自本地主机的“正常”吗?
Posted
技术标签:
【中文标题】Winsock 错误 10054 (WSAECONNRESET) 与 UDP 到/来自本地主机的“正常”吗?【英文标题】:Is Winsock error 10054 (WSAECONNRESET) "normal" with UDP to/from localhost? 【发布时间】:2015-06-10 07:08:14 【问题描述】:“在单个 Windows PC 上使用 UDP 进行进程间通信可能会出现什么问题?”我想...并着手实施它。
但是,尽管仅发送了数百个字节并且只是非常零星地发送,并且尽管 UDP 被用作无连接协议(使用了sendto()
函数),但我还是被随机出现的错误 10054 - “连接重置”所困扰。我觉得这很令人困惑。是吗:
我在某处读到它可能表明另一端没有打开接收端口......但这对我来说更没有意义 - UDP 不是简单地应该发送数据报而不关心会发生什么它?或者当发送到/来自同一台机器(本地主机)上的端口时是否有一些特殊情况?
【问题讨论】:
进一步调查显示,当目标没有任何监听时,Windows 可能会返回 ECONNRESET,而不是 ECONNREFUSED。 看来 Windows recvfrom 文档可能有答案……有待确认。 即使 UDP 是无连接的,也可以在后台发送 ICMP 数据包,让 UDP 发送方知道接收方何时不可用,WinSock 在内部解释这些数据包并可能导致更高级别套接字函数失败。例如,如recvfrom()
所述:“WSAECONNRESET - 远程端执行硬关闭或异常关闭重置了虚拟电路。应用程序应关闭套接字;它不再可用。在UDP-datagram socket 这个错误表明之前的发送操作导致了 ICMP Port Unreachable 消息。" ...
... 并为 sendto()
记录:“WSAECONNRESET - 远程端执行硬或异常关闭重置了虚拟电路。对于 UPD 套接字,远程主机无法传递先前发送的 UDP 数据报并以“端口不可达”ICMP 数据包进行响应。应用程序应关闭套接字,因为它不再可用。“
谷歌搜索这个错误给了我很多与 ECONREFUSED for UDP 相关的 gitlab / github 问题,很多人想知道在这种情况下“连接”甚至意味着什么......迟到的 ICMP 数据包是如此令人困惑“功能”添加。为什么这个概念甚至属于UDP?如果我想要一个连接的 API,我会使用 TCP 或模拟与 UDP 连接的 API。
【参考方案1】:
在我的具体情况下,我有一个在 localhost 上运行的服务器,监听绑定到特定端口的 UDP 套接字。它还有一个绑定到同一个端口的第二个 UDP 套接字(这在上下文中是有意义的),仅用于发送对在第一个套接字上接收到的数据包的响应。
同样在 localhost 上运行的客户端会创建一个临时套接字,向服务器发送一个数据包,等待响应,然后关闭它们的套接字。客户端的超时时间非常短(出于应用程序特定的原因),如果初始尝试超时,则会重试。
有时会发生的情况是客户端向服务器发送一个数据包,在发送响应之前超时,然后关闭其套接字。然后,服务器将(在侦听套接字上)从客户端接收数据包,并(在发送套接字上)发回响应。但是,Windows “有用”地发回一个 ICMP 响应,说明目标端口上不再有任何套接字侦听。至关重要的是,这个数据包最终被传递到侦听套接字,而不是发送套接字(因为它们都共享相同的端口)。在下一次从服务器上的侦听套接字读取时,会收到 WSAECONNRESET
错误,指示它发送的上一个数据包(实际上是从不同的套接字发送的)未能传递。
在我的例子中,解决方法只是忽略侦听套接字上的WSAECONNRESET
错误。发生此类错误后,侦听套接字继续成功接收其他数据包,而发送失败的数据包传递失败后,发送套接字继续成功发送数据包。
【讨论】:
为什么是第二个套接字?通过原始套接字发送有什么问题? 没什么,除了第二个socket发送的端口有时不同,客户端使用响应的源端口来配置自己。以上是关于Winsock 错误 10054 (WSAECONNRESET) 与 UDP 到/来自本地主机的“正常”吗?的主要内容,如果未能解决你的问题,请参考以下文章