Winsock IOCP在断开连接洪水时的怪异行为

时间:2018-10-15 04:30:11

标签: c# winsock iocp

我正在为C#编程一个Socket / Client / Server库,因为我做了很多跨平台编程,却没有找到mono / dotnet / dotnet core在高性能套接字处理方面足够高效。

毫无疑问,linux epoll赢得了性能和可用性的“战斗”,我决定使用类似epoll的界面作为通用API,因此我尝试在{{1}上进行仿真}环境(Windows套接字性能对我来说比linux重要,但界面对我来说不重要)。为此,我直接将WindowsWinsock2 API与封送处理结合使用,而我使用Kernel32

除以下一项外,几乎所有其他东西都工作正常:当我用IOCP创建一个 TCP 服务器并连接到它时,(从本地或通过LAN从远程计算机上执行,没关系)(连接数量超过10000个),所有连接都被接受,没问题,当所有连接都从客户端向服务器发送数据(洪水)时,没问题,服务器接收到所有数据包,但是当我同时断开所有客户端连接时,服务器无法识别所有断开连接事件(即0字节读/可用),通常 1500-8000个客户端卡住。完成事件未触发,因此我无法检测到连接丢失。

服务器不会崩溃,它继续接受新的连接,并且一切正常,仅丢失的连接无法识别

我已经读过-因为使用winsock需要预先分配的读取缓冲区-overlapped IO 读取时会锁定这些缓冲区,并且在完成时释放锁< / em>和如果同时发生太多事件,则由于操作系统限制,它无法锁定所有受影响的缓冲区,这会导致IOCP 无限期挂起< / strong>。

我已阅读到此缓冲区锁定问题的解决方案是,我应该使用零大小的缓冲区,并且将空指针指向缓冲区本身,因此read事件不会将其锁定,而我应该仅使用真实缓冲区当我读取真实数据时。

我已经实现了上述解决方法,除了原来的问题外,它在同时断开数千个客户端的连接后,仍然有效。

当然,我会保持我的代码错误的可能性,因此我使用IOCP的内置dotnet类(如official example所描述的)制作了基本服务器,使用{em> SocketAsyncEventArgs基本相同,并且结果相同

一切正常,除了数千个客户端同时断开连接之外,数千个断开连接(读取断开连接)事件都不会被识别。

我知道我应该进行IO操作,并检查返回值(如果套接字仍可以执行IO),否则,请断开它的连接。问题是在某些情况下我什么也没告诉套接字,我只是接收数据,或者如果我定期执行此操作,这将与轮询几乎相同,并且会因成千上万的连接导致高负载,浪费CPU工作。 >

(我在Windows和Linux客户端上都使用关闭客户端的许多关闭方法,从安全断开连接到正确的TCP套接字关闭,结果总是一样的)

我的问题:

    • 是否有解决此问题的已知方法?
    • 是否有任何有效的方法来识别远程关闭的TCP(优美)连接?
    • 我可以以某种方式将读取超时设置为重叠套接字读取吗?

任何帮助将不胜感激,谢谢!

0 个答案:

没有答案