如何使用的HttpListener同时处理多个连接? [英] How to process multiple connections simultaneously with HttpListener?

查看:286
本文介绍了如何使用的HttpListener同时处理多个连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我构建应用程序,有必要对网络服务器,可以发球,同时,多个客户端。结果
对于我使用的HttpListener 对象。其异步方法\\事件 BeginGetContext EndGetContext 。< BR>
在委托的方法,有一个呼吁听众重新开始听,和它的作品..居多。

In the application that I build, there is a need for webserver that can serve, simultaneously, multiple clients.
For that I use the HttpListener object. with its Async methods\events BeginGetContext and EndGetContext.
In the delegated method, there is a call for the listener to start listening again, and it works.. mostly.

提供的code是code的组合,我发现这里和那里,和延迟,以模拟数据处理瓶颈。

The code provided is a mix of code that i found here and there, and a delay, to simulate a data processing bottleneck.

问题是,它开始管理后,才最后一个被服务的下一个连接..没有用我。

The problem is, it starts to manage the next connection only AFTER the last one was served.. no use for me.

public class HtServer {


    public void startServer(){
        HttpListener HL = new HttpListener();
        HL.Prefixes.Add("http://127.0.0.1:800/");
        HL.Start();
        IAsyncResult HLC = HL.BeginGetContext(new AsyncCallback(clientConnection),HL);   
    }

    public void clientConnection(IAsyncResult res){
        HttpListener listener = (HttpListener)res.AsyncState;
        HttpListenerContext context = listener.EndGetContext(res);
        HttpListenerRequest request = context.Request;
        // Obtain a response object.
        HttpListenerResponse response = context.Response;
        // Construct a response. 
        // add a delay to simulate data process
        String before_wait = String.Format("{0}", DateTime.Now);
        Thread.Sleep(4000);
        String after_wait = String.Format("{0}", DateTime.Now);
        string responseString = "<HTML><BODY> BW: " + before_wait + "<br />AW:" + after_wait + "</BODY></HTML>";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        // Get a response stream and write the response to it.
        response.ContentLength64 = buffer.Length;
        System.IO.Stream output = response.OutputStream;
        // You must close the output stream.
        output.Write(buffer, 0, buffer.Length);
        output.Close();
        listener.BeginGetContext(new AsyncCallback(clientConnection), listener);
    }
}

修改

    private static void OnContext(IAsyncResult ar)
    {
        var ctx = _listener.EndGetContext(ar);
        _listener.BeginGetContext(OnContext, null);

        Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Handling request");

        var buf = Encoding.ASCII.GetBytes("Hello world");
        ctx.Response.ContentType = "text/plain";

        // prevent thread from exiting.
        Thread.Sleep(3000);
        // moved these lines here.. to simulate process delay
        ctx.Response.OutputStream.Write(buf, 0, buf.Length);
        ctx.Response.OutputStream.Close();
        Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " completed");
    }

的输出为

the output is

推荐答案

嘛。那是因为你开始你已经处理后先获取下一个上下文。不要那样做。直接获取下一个背景:

Well. That's because you start to fetch the next context after you have processed the first. Don't do that. Get the next context directly:

public void clientConnection(IAsyncResult res){
    HttpListener listener = (HttpListener)res.AsyncState;
    HttpListenerContext context = listener.EndGetContext(res);

    //tell listener to get the next context directly.
    listener.BeginGetContext(clientConnection, listener);

    HttpListenerRequest request = context.Request;
    // Obtain a response object.
    HttpListenerResponse response = context.Response;
    // Construct a response. 
    // add a delay to simulate data process
    String before_wait = String.Format("{0}", DateTime.Now);
    Thread.Sleep(4000);
    String after_wait = String.Format("{0}", DateTime.Now);
    string responseString = "<HTML><BODY> BW: " + before_wait + "<br />AW:" + after_wait + "</BODY></HTML>";
    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
    // Get a response stream and write the response to it.
    response.ContentLength64 = buffer.Length;
    System.IO.Stream output = response.OutputStream;
    // You must close the output stream.
    output.Write(buffer, 0, buffer.Length);
    output.Close();
}

下面是我的示例code,它证明了它的工作(占OP请求更新):

Here is my sample code that proves that it work (updated per request of the OP):

class Program
{
    private static HttpListener _listener;

    static void Main(string[] args)
    {
        _listener = new HttpListener();
        _listener.Prefixes.Add("http://localhost/asynctest/");
        _listener.Start();
        _listener.BeginGetContext(OnContext, null);

        Console.ReadLine();
    }

    private static void OnContext(IAsyncResult ar)
    {
        var ctx = _listener.EndGetContext(ar);
        _listener.BeginGetContext(OnContext, null);

        Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Handling request");

        var buf = Encoding.ASCII.GetBytes("Hello world");
        ctx.Response.ContentType = "text/plain";

        // simulate work
        Thread.Sleep(10000);

        ctx.Response.OutputStream.Write(buf, 0, buf.Length);
        ctx.Response.OutputStream.Close();


        Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " completed");
    }
}

生成:

两个请求开始得到直接处理。

Both requests starts to get processed directly.

为什么上面code工作

HTTP有一些所谓的流水线。这意味着,在相同的连接收到的所有请求必须得到相同的顺序它们的响应。然而,内置的HttpListener似乎不支持流水线操作,而不是它的完成,用于取第二照顾之前的第一次请求的响应。你确保每个请求是通过一个新的连接发送这是非常重要的。

HTTP have something called pipelining. It means that all requests that are received over the same connection must get their responses in the same order. However, the built in HttpListener doesn't seem to support pipelining, instead it's completes the response for the first request before taking care of the second. It's therefore important that you make sure that every request is sent over a new connection.

要做到这一点,最简单的方法是尝试在code时使用不同的浏览器。我这样做,正如你看到我的两个请求都在同一时间处理。

The easiest way to do that is to use different browsers when trying out the code. I did that, and as you see both my requests are handled at the same time.

这篇关于如何使用的HttpListener同时处理多个连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆