httpListener 回调被调用两次
httpListener callback gets called twice
我遇到了和这个问题一样的问题Here but using the WebClient class on my client and also the second code example from 。
那么我该怎么做才能只接到来自我的 WebClient 客户端的一个电话呢?
我的 httplistener 回调被调用了两次,第一次没问题,但第二次在 HttpListenerContext context = Listener.EndGetContext(ar);
处抛出此错误
System.Net.HttpListenerException: 'The I/O operation has been aborted because of either a thread exit or an application request'
服务器代码:
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);
}
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() itself can't accept a cancellation token. It can be aborted though by calling 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();
}
}
我遇到了和这个问题一样的问题Here but using the WebClient class on my client and also the second code example from
那么我该怎么做才能只接到来自我的 WebClient 客户端的一个电话呢?
我的 httplistener 回调被调用了两次,第一次没问题,但第二次在 HttpListenerContext context = Listener.EndGetContext(ar);
System.Net.HttpListenerException: 'The I/O operation has been aborted because of either a thread exit or an application request'
服务器代码:
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);
}
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() itself can't accept a cancellation token. It can be aborted though by calling 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();
}
}