C#使用HTTPListener异步实现HTTP服务端,请求执行两次
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#使用HTTPListener异步实现HTTP服务端,请求执行两次相关的知识,希望对你有一定的参考价值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using DevSDK.Net.Sockets;
using System.IO;
namespace ConsoleApplication1
class Program
static HttpListener sSocket = null;
static void Main(string[] args)
sSocket = new HttpListener();
sSocket.Prefixes.Add("http://127.0.0.1:8080/");
sSocket.Start();
sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
Console.Read();
static void GetContextCallBack(IAsyncResult ar)
try
sSocket = ar.AsyncState as HttpListener;
HttpListenerContext context = sSocket.EndGetContext(ar);
sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
// 该方法是我要进行的操作
CommonMethod();
catch
不是,我只想一个请求执行一次,但是一个请求进来后却执行了两次后,才会停下来等待接收另一个请求
参考技术B不知道你的请求是否是从浏览器访问的,我的是浏览器访问,执行2次的原因是因为确实请求2次,具体看截图。
异步 HttpListener 每个请求被接收两次
【中文标题】异步 HttpListener 每个请求被接收两次【英文标题】:Asynchronous HttpListener has each request is received twice 【发布时间】:2011-05-05 08:57:39 【问题描述】:我在 C# 中实现了一个异步 http 监听器。
我按照here by Microsoft提供的教程进行操作
发现了另一个教程,我愚蠢地没有加入书签,现在再也找不到了。这意味着我有一些我不会自己编写的代码,但提供的解释是有道理的,所以我遵循了。
现在我面临两个问题:
首先,我必须在每次请求后使用 Listener.Stop() 重新启动侦听器,然后再次调用 StartListening 方法,其次,当我这样做时,我会收到每个请求两次。 该请求确实被发送了两次,但我收到了两次。 但是,当我暂停正在收听的线程约 2 秒时,它不会收到两次。
如果我的解释含糊不清,我很抱歉,但我对我的问题的理解也是如此,我不知道是什么原因造成的。 由于回调方法是大多数事情发生的地方,所以我将发布它,如果您需要更多代码,请告诉我。 任何帮助将不胜感激,因为我真的坚持这个。
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)
【问题讨论】:
不知道是什么调用了这个回调,不知道WaitHandle的listenForNextRequest是怎么用的,ListenAsynchronously做了什么方法,有点猜谜游戏。 对不起,我添加了代码 您应该将一些有用的调试信息打印到控制台(或记录到文件,如果您愿意)并在此处发布。请指定您用于运行此代码的操作系统及其版本。这样会更简单地尝试帮助您...问候,贾科莫 【参考方案1】:我不确定您为什么在您的 ListenerCallback()
方法中调用 StopListening()
和 ListenAsynchronously()
。 Listen()
方法正在线程中运行,并将继续获取每个下一个传入请求。如果我在写这个,我就不会使用 HttpListener 的实例变量。在您的 ListenAsynchronously 方法中创建一个新的并将其传递到您的状态对象中,例如,
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)
【讨论】:
我用它作为从 .Net 2.0 应用程序中提供简单页面的基础,我对它的运行效果印象深刻。在我的笔记本电脑上,我能够为一个简单的单线程负载测试脚本每秒处理大约 130-200 个请求,同时为该测试脚本的 5 个实例中的每一个实例提供大约 20 个请求。在这些测试中,服务器代码使用了我大约 12% 的 CPU。以上是关于C#使用HTTPListener异步实现HTTP服务端,请求执行两次的主要内容,如果未能解决你的问题,请参考以下文章