class Program { private static Socket _Socket = new Socket( AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); private static void Main(string[] args) { _Socket.Bind(new IPEndPoint(IPAddress.Any,5012)); _Socket.Listen(100); var arguments = new SocketAsyncEventArgs(); arguments.Completed += OnAccepted; Accept(arguments); Console.ReadLine(); } private static void Accept(SocketAsyncEventArgs args) { args.AcceptSocket = null; if (!_Socket.AcceptAsync(args)) OnAccepted(null,args); } private static void OnAccepted(object sender,SocketAsyncEventArgs e) { Console.WriteLine("Accepted."); Accept(e); } }
这里有趣的是如果我在这一行放置一个断点并调试它:
var arguments = new SocketAsyncEventArgs();
在继续执行之前使用Hercules连接此服务器,它就像一个魅力.我在开始时这样做,然后神奇地,OnAccepted被调用并写入“已接受”.每个连接上的控制台.我在使用Windows 7和.NET 4的机器上使用相同的代码和相同的程序(Hercules),但它始终有效.
>我做错了什么?
>如果没有,它是我的操作系统或.NET Framework 4.5版的已知错误吗?
>任何人都可以重现这个吗?
编辑:两个操作系统都是64位.
编辑2:我将此报告为Microsoft Connect,here上的错误.
编辑3:找到一个解决方法并将其发布到Connect(只需创建一个虚假的第一个连接).
编辑4:如果有人可以重现这一点,请加入Connect中的问题.
编辑5:我看到了question Thomas has mentioned,我测试了Console.ReadLine是否导致了这个问题.原来是.如果我在Console.ReadLine调用之前添加Thread.Sleep(3000)并在运行程序后3秒内进行连接尝试,它就像魅力一样.同样,奇怪的是我在调用Console.ReadLine之前只需执行一次.如果在调用Console.ReadLine之前建立一个连接,则每个连续的连接都会起作用,即使在调用Console.ReadLine之后也是如此.我将在Conect页面中提到这一点.
编辑6:我将另一个问题的链接添加到Connect页面,并添加了另一个解决方法,涉及在调用Console.ReadLine之前调用Thread.Sleep,就像我在上面的编辑中提到的那样.
解决方法
所以我在问题中给出的代码示例中应该做的是改变这一行:
Accept(arguments);
在Main方法中的这一行:
Task.Run(() => Accept(arguments)).Wait();
这可以防止Console.ReadLine()调用阻止IOCP操作.
作为旁注:这只是一个操作系统错误的解决方法,它很可能通过更新来修复 – 并且 – 这使得此解决方案变得多余.
最新版本的Windows 8已修复此问题.
编辑:feedback item I have posted in Connect的状态更改为“按设计”.
我还收到了一封电子邮件,其中包含以下内容:
The underlying issue for this behavior has to do with how IO
Completion Ports are handled in Windows 8. .NET works using the
completion ports; when their behavior changed,so did the .NET
behavior.
编辑2:反馈状态再次更改为“活动”,没有详细信息.
编辑3:反馈收到了微软的另一个答案,说明:
The latest version of Windows 8 should have this fixed. Note that it’s an OS issue,not a .NET issue: you need to make sure you have the latest version of the OS. No changes were made to .NET to either cause or fix this issue.”