我也遇到类似的问题Here,但是我在客户端上使用了WebClient类,还使用了this answere中的第二个代码示例。
那么我该怎么做才能只得到一个从我的WebClient客户端拨打电话?
我的httplistener回调被调用了两次,第一个没问题,但是第二个在HttpListenerContext context = Listener.EndGetContext(ar);
System.Net.HttpListenerException:'由于线程退出或应用程序请求,I / O操作已中止'
服务器代码:
private void DoWork(object arg)
{
Listener = new HttpListener();
Listener.Prefixes.Add("https://+:28210");
Listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
Console.WriteLine("Listening...");
Listener.Start();
Listener.BeginGetContext(ListenerContext, null);
Console.ReadKey();
}
`
private static void ListenerContext(IAsyncResult ar)
{
Console.WriteLine("Get Data...");
HttpListenerContext context = Listener.EndGetContext(ar);
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
Listener.BeginGetContext(ListenerContext, null);
Console.WriteLine("Got Data!");
//Some more Code...
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseData);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
}
客户代码:
using (WebClient client = new WebClient())
{
string serialisedData = JsonConvert.SerializeObject(Data);
client.Credentials = new NetworkCredential(config.UserData.Username, config.UserData.Password);
byte[] responsebyte = client.UploadData(config.ServerAddress, System.Text.Encoding.UTF8.GetBytes(serialisedData));
response = System.Text.Encoding.UTF8.GetString(responsebyte);
}
答案 0 :(得分:1)
HttpListener's文档中的示例可用于仅处理 个呼叫。要处理更多呼叫,listener.Start()
和listener.Stop()
之间的代码必须循环运行。
要使此代码异步,所需要做的就是使用HttpListener.GetContext
和Stream.Write
的异步版本:
public static async Task ListenAsync(params string[] prefixes)
{
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
using(var listener = new HttpListener())
{
// Add the prefixes.
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening...");
for (int i=0;i<3;i++)
{
var context = await listener.GetContextAsync();
Console.WriteLine($"Got {i}");
var response = context.Response;
string responseString = $"<HTML><BODY> Hello world {i}!</BODY></HTML>";
var buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
using(var output = response.OutputStream)
{
await output.WriteAsync(buffer,0,buffer.Length);
}
}
listener.Stop();
}
}
ListenAsync
必须仅被调用一次并等待直到完成。在这种情况下,退出前它最多可循环处理3个请求。
在控制台应用程序中调用它可以很简单:
static async Task Main(string[] args)
{
Console.WriteLine("Starting !");
await ListenAsync(@"http://*:19999/");
Console.WriteLine("Finished");
}
要以线程安全的方式停止侦听器,必须使用CancellationToken表示侦听器必须取消。 GetContextAsync()本身不接受取消令牌。尽管可以通过调用HttpListener.Abort中止该操作。如果GetContextAsync()
在等待时发生,将抛出ObjectDisposedException
。
main方法现在要等待按键,然后发出取消信号并等待ListenAsync
完成当前请求:
static async Task Main(string[] args)
{
Console.WriteLine("Starting !");
using(var cts=new CancellationTokenSource())
{
try
{
var task= ListenAsync(cts.Token, @"http://*:19999/");
Console.ReadKey();
cts.Cancel();
await task;
}
catch(ObjectDisposedException)
{
Console.WriteLine("Listener aborted");
}
}
Console.WriteLine("Finished");
}
ListenAsync
本身在取消令牌上使用token.Register(()=>listener.Abort());
来中止侦听器。 for
循环更改为while(!token.IsCancellationRequested)
,使收听者可以继续收听,直到按下某个键为止:
public static async Task ListenAsync(CancellationToken token,params string[] prefixes)
{
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
using(var listener = new HttpListener())
{
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening. Hit any key to end.");
//Abort if the token is signalled
token.Register(()=>listener.Abort());
int i=0;
//Loop until cancellation is requested
while (!token.IsCancellationRequested)
{
var context = await listener.GetContextAsync();
Console.WriteLine($"Got {i++}");
var response = context.Response;
string responseString = $"<HTML><BODY> Hello world {i}!</BODY></HTML>";
var buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
using(var output = response.OutputStream)
{
await output.WriteAsync(buffer,0,buffer.Length);
}
}
listener.Stop();
}
}