异步的HttpListener已每个请求收到两次 [英] Asynchronous HttpListener has each request is received twice
问题描述
我已经实现了在C#中的异步HTTP侦听器。
我跟着提供的教程这里由微软一>
和发现另一个教程,我愣神不书签,现在找不到了。这意味着我有,我就不会写这样一些code自己,而是提供有意义的解释,所以我接着说。
现在我面临着两个问题:
首先,我已经和一次第二,Listener.Stop()每个请求后,重新启动监听器,然后调用StartListening方法,当我这样做,我收到的每个请求的两倍。 该请求中网被发送两次,但我得到了两遍。 但是,它没有得到的时候我暂停线程我听的约2秒钟收到两次。
我很抱歉,如果我在我的解释很含糊,但让我我的问题的理解,我不知道是什么原因造成的。 由于回调方法是大多数的事情发生,我只是张贴,请告诉我,如果你需要更多的code。 任何帮助将非常乐意AP preciated,因为我真的很坚持这一点。
公共无效ListenAsynchronously()
{
如果(监听器prefixes.Count == 0)的foreach(字符串s $ p中$ pfixes)监听器prefixes.Add(S)。
尝试
{
listener.Start();
}
赶上(例外五)
{
Logging.logException(E);
}
System.Threading.ThreadPool.QueueUserWorkItem(新System.Threading.WaitCallback(听));
}
私人无效听(对象状态)
{
而(listener.IsListening)
{
listener.BeginGetContext(新的AsyncCallback(ListenerCallback),监听器);
listenForNextRequest.WaitOne();
}
}
私人无效ListenerCallback(IAsyncResult的AR)
{
的HttpListener的HttpListener = ar.AsyncState为System.Net.HttpListener;
System.Net.HttpListenerContext上下文= NULL;
INT requestNumber = System.Threading.Interlocked.Increment(REF requestCounter);
如果(的HttpListener == NULL)回报;
尝试
{
上下文= httplistener.EndGetContext(AR);
}
赶上(例外前)
{
返回;
}
最后
{
listenForNextRequest.Set();
}
如果(背景== NULL)回报;
System.Net.HttpListenerRequest请求= context.Request;
如果(request.HasEntityBody)
{
使用(就是System.IO.StreamReader SR =新就是System.IO.StreamReader(request.InputStream,request.ContentEncoding))
{
字符串=的RequestData sr.ReadToEnd();
//东西我做的请求,发生在这里
}
}
尝试
{
使用(System.Net.HttpListenerResponse响应= context.Response)
{
//响应的东西在这里发生
}
byte []的缓冲区= System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(缓冲液,0,buffer.Length);
response.Close();
的stopListening();
//如果我不设置线程睡在这里,我收到了双倍的请求
System.Threading.Thread.Sleep(2500);
ListenAsynchronously();
}
}
赶上(例外五)
{
}
}
我不知道你为什么叫的stopListening()
和 ListenAsynchronously( )
在 ListenerCallback()
方法。该收听()
方法正在运行一个线程,并会继续得到各下一传入的请求。如果我写这个,我也不会用的HttpListener的实例变量。在ListenAsynchronously方法创建一个新的,并通过它在你的状态对象,例如,
公共类HttpListenerCallbackState
{
私人只读的HttpListener _listener;
私人只读的AutoResetEvent _listenForNextRequest;
公共HttpListenerCallbackState(的HttpListener监听器)
{
如果(听众== NULL)抛出新ArgumentNullException(监听器);
_listener =侦听器;
_listenForNextRequest =新的AutoResetEvent(假);
}
公众的HttpListener监听{{返回_listener; }}
公众的AutoResetEvent ListenForNextRequest {{返回_listenForNextRequest; }}
}
公共类的Htt prequestHandler
{
私人诠释requestCounter = 0;
私人ManualResetEvent的stopEvent =新的ManualResetEvent(假);
公共无效ListenAsynchronously(IEnumerable的<字符串> prefixes)
{
的HttpListener监听器=新的HttpListener();
的foreach(字符串s $ p中$ pfixes)
{
。监听器prefixes.Add(S);
}
listener.Start();
HttpListenerCallbackState状态=新HttpListenerCallbackState(听众);
ThreadPool.QueueUserWorkItem(听,状态);
}
公共无效的stopListening()
{
stopEvent.Set();
}
私人无效听(对象状态)
{
HttpListenerCallbackState callbackState =(HttpListenerCallbackState)状态;
而(callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(新的AsyncCallback(ListenerCallback),callbackState);
INT N = WaitHandle.WaitAny(新的WaitHandle [] {callbackState.ListenForNextRequest,stopEvent});
如果(正== 1)
{
// stopEvent是信号
callbackState.Listener.Stop();
打破;
}
}
}
私人无效ListenerCallback(IAsyncResult的AR)
{
HttpListenerCallbackState callbackState =(HttpListenerCallbackState)ar.AsyncState;
HttpListenerContext上下文= NULL;
INT requestNumber = Interlocked.Increment(REF requestCounter);
尝试
{
上下文= callbackState.Listener.EndGetContext(AR);
}
赶上(例外前)
{
返回;
}
最后
{
callbackState.ListenForNextRequest.Set();
}
如果(背景== NULL)回报;
HttpListenerRequest请求= context.Request;
如果(request.HasEntityBody)
{
使用(就是System.IO.StreamReader SR =新就是System.IO.StreamReader(request.InputStream,request.ContentEncoding))
{
字符串=的RequestData sr.ReadToEnd();
//东西我做的请求,发生在这里
}
}
尝试
{
使用(HttpListenerResponse响应= context.Response)
{
//响应的东西在这里发生
字符串responseString =确定;
byte []的缓冲区= Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(缓冲液,0,buffer.Length);
response.Close();
}
}
赶上(例外五)
{
}
}
}
I have implemented an asynchronous http listener in c#.
I followed the tutorial provided here by Microsoft
and found another tutorial which i stupidly not bookmarked and now can't find again. Meaning that I have some code that I would not have written that way myself but the explanations provided made sense so I followed that.
Now I am facing two problems:
First, I have to restart the listener after each request with Listener.Stop() and then call the StartListening method and again and second, when I do this, I receive each request twice. The request does net get sent twice, but I receive it twice. It does not however get received twice when I pause the Thread I am listening on for about 2 seconds.
I am sorry if I am quite vague in my explanations, but so is my understanding of my problem, I have no idea what is causing it. Since the callback method is where most of the stuff happens, I will just post it, please tell me if you need any more code. Any help will be gladly appreciated, since I am really stuck on this one.
public void ListenAsynchronously()
{
if (listener.Prefixes.Count == 0) foreach (string s in prefixes) listener.Prefixes.Add(s);
try
{
listener.Start();
}
catch (Exception e)
{
Logging.logException(e);
}
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Listen));
}
private void Listen(object state)
{
while (listener.IsListening)
{
listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
listenForNextRequest.WaitOne();
}
}
private void ListenerCallback(IAsyncResult ar)
{
HttpListener httplistener = ar.AsyncState as System.Net.HttpListener;
System.Net.HttpListenerContext context = null;
int requestNumber = System.Threading.Interlocked.Increment(ref requestCounter);
if (httplistener == null) return;
try
{
context = httplistener.EndGetContext(ar);
}
catch(Exception ex)
{
return;
}
finally
{
listenForNextRequest.Set();
}
if (context == null) return;
System.Net.HttpListenerRequest request = context.Request;
if (request.HasEntityBody)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
{
string requestData = sr.ReadToEnd();
//Stuff I do with the request happens here
}
}
try
{
using (System.Net.HttpListenerResponse response = context.Response)
{
//response stuff happens here
}
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
response.Close();
StopListening();
//If I dont set the thread to sleep here, I receive the double requests
System.Threading.Thread.Sleep(2500);
ListenAsynchronously();
}
}
catch (Exception e)
{
}
}
I am not sure why you are calling StopListening()
and ListenAsynchronously()
in your ListenerCallback()
method. The Listen()
method is being run in a thread and will continue to get each next incoming request. If I was writing this, I would not be using a instance variable of HttpListener. Create a new one in your ListenAsynchronously method and pass it in your state object, for example,
public class HttpListenerCallbackState
{
private readonly HttpListener _listener;
private readonly AutoResetEvent _listenForNextRequest;
public HttpListenerCallbackState(HttpListener listener)
{
if (listener == null) throw new ArgumentNullException("listener");
_listener = listener;
_listenForNextRequest = new AutoResetEvent(false);
}
public HttpListener Listener { get { return _listener; } }
public AutoResetEvent ListenForNextRequest { get { return _listenForNextRequest; } }
}
public class HttpRequestHandler
{
private int requestCounter = 0;
private ManualResetEvent stopEvent = new ManualResetEvent(false);
public void ListenAsynchronously(IEnumerable<string> prefixes)
{
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
HttpListenerCallbackState state = new HttpListenerCallbackState(listener);
ThreadPool.QueueUserWorkItem(Listen, state);
}
public void StopListening()
{
stopEvent.Set();
}
private void Listen(object state)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)state;
while (callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
if (n == 1)
{
// stopEvent was signalled
callbackState.Listener.Stop();
break;
}
}
}
private void ListenerCallback(IAsyncResult ar)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)ar.AsyncState;
HttpListenerContext context = null;
int requestNumber = Interlocked.Increment(ref requestCounter);
try
{
context = callbackState.Listener.EndGetContext(ar);
}
catch (Exception ex)
{
return;
}
finally
{
callbackState.ListenForNextRequest.Set();
}
if (context == null) return;
HttpListenerRequest request = context.Request;
if (request.HasEntityBody)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
{
string requestData = sr.ReadToEnd();
//Stuff I do with the request happens here
}
}
try
{
using (HttpListenerResponse response = context.Response)
{
//response stuff happens here
string responseString = "Ok";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
response.Close();
}
}
catch (Exception e)
{
}
}
}
这篇关于异步的HttpListener已每个请求收到两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!