![](/img/trans.png)
[英]Is it possible to call HttpListener.GetContext with a timeout?
[英].Net HttpListener.GetContext() gives “503 Service Unavailable” to the client
我想在C#中编写一个非常简单的自定义Http服务器。
实现连接的代码就像.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() works -- the URL is properly reserved for the correct user with 'netsh http add urlacl...'., else Start() would throw. The URL is also only reserved once
listener.Start() works -- the URL is properly reserved for the correct user with 'netsh http add urlacl...'., else Start() would throw. The URL is also only reserved once
。
我可以看到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/中记录的本机HttpReceiveHttpRequest方法。 desktop / aa364495(v = vs.85).aspx 。 所以它是拒绝我的请求的本机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
因此,作为一种解决方法,我可以实现我自己的http请求解析器和响应生成器...而不是我喜欢被迫重新发明轮子。
我刚遇到同样的问题,它是由URL ACL引起的。
从提升的命令提示符
netsh http show urlacl
将显示所有URL ACL
netsh http delete urlacl http://+:1234/
将使用URL http://+:1234/
删除URL ACL
netsh http add urlacl url=http://+:1234/ user=Everyone
都会添加一个任何本地用户都可以监听的URL ACL(通常这应该使用网络服务帐户)
此URL需要与HttpListener
中的前缀匹配。
如果您只是在侦听localhost,则不需要URL ACL。
通常,没有正确的URL ACL会在启动侦听器时导致权限错误。 我不确定具体情况是什么导致它超过此但是然后在GetContext
上返回503服务不可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.