我正在为C#
编程一个Socket / Client / Server库,因为我做了很多跨平台编程,却没有找到mono
/ dotnet
/ dotnet core
在高性能套接字处理方面足够高效。
毫无疑问,linux
epoll
赢得了性能和可用性的“战斗”,我决定使用类似epoll的界面作为通用API,因此我尝试在{{1}上进行仿真}环境(Windows套接字性能对我来说比linux重要,但界面对我来说不重要)。为此,我直接将Windows
和Winsock2
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套接字关闭,结果总是一样的)
我的问题:
任何帮助将不胜感激,谢谢!