Windows 8 - .NET TCP AcceptAsync 回调未触发(被 Console.ReadLine() 阻止)
Posted
技术标签:
【中文标题】Windows 8 - .NET TCP AcceptAsync 回调未触发(被 Console.ReadLine() 阻止)【英文标题】:Windows 8 - .NET TCP AcceptAsync callback not firing (blocked by Console.ReadLine()) 【发布时间】:2012-09-17 17:19:53 【问题描述】:我遇到了特定于 Windows 8 和 VS2012 的问题。
我有一个 TCP 套接字服务器和客户端,并且正在本地网络上进行一些测试。使用 sysinternals TCPView,我可以看到数据包从 TCP 客户端发送并到达 TCP 服务器(我看到数据包计数器增加了)。
但是,数据似乎没有进入应用程序堆栈? 完全相同的构建在 Windows 7 上运行没有问题。
我关闭了 Windows 8 防火墙,并在关闭 UAC 的域管理员用户上以提升的权限运行这两个进程。
当我将客户端连接到外部服务器(在单独的机器上运行)时,一切正常。 Windows 8 中是否还有其他东西可以禁止本地进程之间的 TCP 数据通信?
谢谢,
编辑
为了确保我的服务器应用程序中没有任何东西导致此问题,我在控制台应用程序中构建了一个快速 TCP 服务器,并为套接字构造函数使用以下代码:
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
并在与我的服务器应用程序相同的本地 IP/端口上侦听。 我遇到了同样的问题,我可以远程登录到端口,但 listenerSocket.AcceptAsync 永远不会被命中。
编辑 2
经过进一步测试,我发现我的问题与使用异步套接字调用有关,即如果我使用像 socket.Accept() 这样的同步调用,则测试应用程序运行正常。但是,当我使用异步套接字调用时,即 socket.AcceptAsync(),我遇到了提到的问题。到目前为止,在异步套接字调用方面,我找不到任何关于 win7 和 8 之间差异的提及。
这是我的快速示例应用程序,它显示异步回调从未被触发。此 sn-p 在 Windows 7 中运行良好,但在 Windows 8 中无法运行(尝试 telnet 到 127.0.0.1 : 7000)。
class Program
private static SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
static void Main(string[] args)
var listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenerSocket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7000));
listenerSocket.Listen(100);
socketAsyncEventArgs.Completed += AcceptEventArg_Completed;
listenerSocket.AcceptAsync(socketAsyncEventArgs);
Console.ReadLine();
private static void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
Console.WriteLine("AcceptEventArg_Completed");
编辑 3
我发现另外 2 个人在 Microsoft Connect 上报告了同样的问题: https://connect.microsoft.com/VisualStudio/feedback/details/759913/socketasynceventargs-completed-doesnt-fire-in-net-framework-4-5 和 http://connect.microsoft.com/VisualStudio/feedback/details/747218/saea-not-working-in-net-4-5-rp
而第二个很有趣,因为它似乎得出结论,在 Console.ReadLine() 调用中存在 Windows 错误,它导致了问题并阻止了异步回调。如果我将我的 sn-p 中的 Console.ReadLine() 替换为:
while (true)
System.Threading.Thread.Sleep(10);
一切正常。
【问题讨论】:
你是通过机器的公网IP还是通过localhost通信? 本地网络IP(不是localhost) 好吧,我强烈怀疑是防火墙问题,但由于我现在无法测试,所以我只能这样做,抱歉。您是否尝试在 Windows 防火墙中手动允许服务器应用? 您似乎拥有服务器和客户端的源代码,因此我建议您尝试在调试器中运行服务器以查看发生了什么。或者添加日志,以便您可以看到各种套接字的状态。这听起来确实像是某种 TCP 驱动程序设置问题,例如可能使用 IPv6 而不是 IPv4,反之亦然。因此,还要检查您的设备驱动程序设置。 windows.microsoft.com/en-US/windows7/Change-TCP-IP-settings 我这样做了,奇怪的是我看到 TcpView 注册了数据包,但在应用程序堆栈中(调试时)TCP 数据包没有到达,因此我怀疑某种安全设置禁止数据流向应用程序 【参考方案1】:看到这个:GetQueuedCompletionStatus can't dequeue IO from IOCP if the thread which originally issued the IO is blocking in ReadFile under windows 8
这是 Windows 8 和 2012 中的一个错误,会影响所有使用 AcceptEx 和 ReadFile 的程序。目前,已知只有这两个功能受到影响。
【讨论】:
【参考方案2】:我在使用 SocketAsyncEventArgs 开发 Tcp 服务器和客户端应用程序时遇到了同样的事情
我建议你先试试这个。
打开具有高级安全性的 Windows 防火墙 检查入站/出站规则以查看您的应用程序是否被阻止。
打开 AssemblyInfo.cs 并更改
[程序集:Guid("06985fe3-80eb-48b4-940a-fd926e2f2053")]
到任何其他 guid 值。
通过更改此设置,windows 会认为这是一个新应用程序,如果对旧应用程序有任何限制,它将不会出现在新应用程序上。
【讨论】:
【参考方案3】:听起来像这个与 Windows 8 上的 IOCP 处理(可能只是 AcceptEx)相关的 Windows 错误,而其他阻塞 I/O 正在同一线程上进行:
http://social.technet.microsoft.com/Forums/en-GB/winserver8gen/thread/5764cd0f-fda1-4cfa-ae35-808210bae77e
因此套接字连接被接受,但您的应用永远不会收到它的通知。
也许 Windows 8 做了一些奇怪的、有点坏掉的巫术来将像 Console.Read 这样的同步 IO 在内部转换为异步。
您可以将您的服务器代码移动到不同的线程,尝试其他解决方法可能是同步执行 Accept 或将控制台处理更改为异步(我无法真正尝试,因为我没有 Windows 8 )。
【讨论】:
以上是关于Windows 8 - .NET TCP AcceptAsync 回调未触发(被 Console.ReadLine() 阻止)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 TCP 或 UDP 将数据从 Windows Phone 8.1 发送到 PC?
升级到 Windows 10 后 net.tcp 无法正常工作
TCP 错误代码 10061:无法连接到 net.tcp://。连接尝试持续了 00:00:01.0156241 的时间跨度
域服务器和域外客户端中的 net.tcp wcf 服务(托管 Windows 服务)