gpt4 book ai didi

c# - 如何使用 HttpListener 同时处理多个连接?

转载 作者:太空狗 更新时间:2023-10-29 17:32:36 28 4
gpt4 key购买 nike

在我构建的应用程序中,需要可以同时为多个客户端提供服务的网络服务器。
为此,我使用了 HttpListener 对象。及其 Async 方法\事件 BeginGetContextEndGetContext
在委托(delegate)方法中,调用监听器再次开始监听,并且它起作用了……主要是。

所提供的代码是我在这里和那里找到的代码的混合,以及一个延迟,以模拟数据处理瓶颈。

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

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");
}

输出是 enter image description here

最佳答案

嗯。那是因为您在处理完第一个上下文后开始获取下一个上下文。不要那样做。直接获取下一个上下文:

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();
}

这是我证明它有效的示例代码(根据 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");
}
}

生成:

enter image description here

两个请求都开始直接处理。

为什么上面的代码有效

HTTP 有一种叫做流水线的东西。这意味着通过同一连接接收到的所有请求必须以相同的顺序得到响应。但是,内置的 HttpListener 似乎不支持流水线,而是在处理第二个请求之前完成对第一个请求的响应。因此,确保每个请求都通过新连接发送很重要。

最简单的方法是在尝试代码时使用不同的浏览器。我这样做了,如您所见,我的两个请求是同时处理的。

关于c# - 如何使用 HttpListener 同时处理多个连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28273345/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com