实现连接的代码就像.Net提供的那样简单:
// get our IPv4 address IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName()); IPAddress theAddress = localIPs.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault(); // Create a http listener. var listener = new HttpListener(); string myUrlPrefix = $"http://{theAddress.ToString()}:{port}/MyService/"; listener.Prefixes.Add(myUrlPrefix); Console.WriteLine($"Trying to listen on {myUrlPrefix}"); listener.Start(); Console.WriteLine("Listening..."); HttpListenerContext context = null; try { context = listener.GetContext(); } catch(Exception ex) { Console.WriteLine(ex.Message); } HttpListenerRequest request = context.Request;
运行它时,GetContext()会阻塞,永远不会返回并且不会抛出异常.
listener.Start()工作 – 使用’netsh http add urlacl …’为正确的用户正确保留URL.否则Start()将抛出.该URL也只保留一次.
我可以看到netstat -na正在监听端口.
我试图通过浏览器或wget的cygwin实现来访问它.两者都给我“ERROR 503:Service Unavailable.”.
这是wget输出:
$wget http://127.0.0.1:45987/MyService/ --2016-03-06 14:54:37-- http://127.0.0.1:45987/MyService/ Connecting to 127.0.0.1:45987... connected. HTTP request sent,awaiting response... 503 Service Unavailable 2016-03-06 14:54:37 ERROR 503: Service Unavailable.
这意味着TCP连接已建立,但HttpListener.GetContext()并不打算为请求提供服务并给我上下文,它也至少不会抛出异常来告诉我什么是错误的.它只是关闭连接.从调试输出来看,它内部甚至没有First-Chance异常.
我上下搜索了Net和Stackoverflow,但没有找到任何有用的东西.
Windows事件日志中没有错误.
这是Windows 10 Pro和Microsoft Visual Studio社区2015
版本14.0.23107.0 D14REL与Microsoft .NET Framework版本4.6.01038.
值得一提的是,我还测试了所有防火墙关闭,仍然是相同的结果.
有没有人知道GetContext()中可能出现什么问题以及我如何调试或解决这个问题?
======
编辑:我已启用.Net Framework源步进并已进入GetContext().阻止和拒绝服务http请求发生在名为“UnsafeNclNativeMethods.HttpApi.HttpReceiveHttpRequest”的东西中,我想这可能是https://msdn.microsoft.com/en-us/library/windows/desktop/aa364495(v=vs.85).aspx中记录的本机HttpReceiveHttpRequest方法.所以它是拒绝我的请求的本机API.
解决方法
有趣的是,如果我更深层次并使用普通的TcpListener,我可以毫无疑问地接收纯文本请求.
// Create a Tcp listener. mTcpListener = new TcpListener(theAddress,port); Console.WriteLine($"Trying to listen on {theAddress}:{port}"); mTcpListener.Start(); Console.WriteLine("Listening..."); Socket socket = null; try { socket = mTcpListener.AcceptSocket(); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } // wait a little for the socket buffer to fill up await Task.Delay(20); int bytesAvailable = socket.Available; var completeBuffer = new List<byte>(); while (bytesAvailable > 0) { byte[] buffer = new byte[bytesAvailable]; int bytesRead = socket.Receive(buffer); completeBuffer.AddRange(buffer.Take(bytesRead)); bytesAvailable = socket.Available; } byte[] receivedBytes = completeBuffer.ToArray(); string receivedString = Encoding.ASCII.GetString(receivedBytes);
… 奇迹般有效.返回的字符串是
GET /MyService/ HTTP/1.1 User-Agent: Wget/1.17.1 (cygwin) Accept: */* Accept-Encoding: identity Host: 127.0.0.1:45987 Connection: Keep-Alive
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。