![](/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.