使用多线程处理多个http请求HttpListener导致奇怪的行为

Posted

技术标签:

【中文标题】使用多线程处理多个http请求HttpListener导致奇怪的行为【英文标题】:Handle multiple http request HttpListener using multithread leads to strange behavior 【发布时间】:2021-11-26 18:35:28 【问题描述】:

我正在尝试创建一个 HttpListener 并接受 Http 请求,对于每个 HttpListenerContext 我创建一个专用线程来像这样处理它

while(true)

    var context = listener.GetContext();
    Thread backgroundThread = new Thread(() => HandleContext(context));
    backgroundThread.Start();

HandleContext 我做一个Thread.Sleep(5000) 来模拟工作和Console.WriteLine(DateTime.Now) 用于调试目的。 但是当我同时在 Chrome 中打开 3 个标签时,只有 2 个标签返回,但结果重复,最后一个标签一直挂着。

据我所知,我的线程没有可能导致死锁的共享数据,但这种行为似乎是死锁,你能告诉我我做错了什么以及如何解决它吗?

这是我的完整代码

class Program
    
        private static HttpListener _listener;
        static void Main(string[] args)
        
            HttpListener listener = new HttpListener();
            listener.Prefixes.Add("http://localhost:5001/");
            listener.Start();

            Listen(listener);
        

        static void Listen(HttpListener listener)
        
            while (true)
            
                var context = listener.GetContext();
                Thread backgroundThread = new Thread(() => HandleContext(context));
                backgroundThread.Start();
            
        

        static void HandleContext(HttpListenerContext context)
        
            Thread.Sleep(5000);

            Console.WriteLine($"Hello world, DateTime.Now");

            var responseContent = "Hello world";

            var buffer = Encoding.UTF8.GetBytes(responseContent);

            context.Response.OutputStream.Write(buffer, 0, buffer.Length);

            context.Response.OutputStream.Close();
            context.Response.Close();
        
    

【问题讨论】:

您在static void Listen(HttpListener listener) 方法的开头有一个“孤儿”listener.GetContext();。不会处理此上下文,这解释了您的标签“空”。 @Madhatter 能不能再具体点,context 是在backgroundThread 中传递的,线程是在同一个Context 范围内启动的,那为什么会是“孤儿”呢? 在您发布的代码中有两个listener.GetContext();。第一个永远不会发送到HandleContext 方法 对不起,我的错。这不是我打算做的。但是 Console.WriteLine 仍然被复制 【参考方案1】:

过了一会儿,我发现类似“死锁”的行为是由于@Mat Hatter 指出的“孤儿”GetContext 而发生的。由于谷歌浏览器发送 2 个请求的行为,Console.WriteLine 被复制,1 个用于网站内容,1 个用于 fav.icon。因此,Console.WriteLine 被复制并没有错。

【讨论】:

【参考方案2】:

您没有设置HttpListenerResponse 流的ContentLength64 属性! 请试试这个

context.Response.ContentLength64 = buffer.LongLength;
using (Stream stream = context.Response.OutputStream)

    stream.Write(buffer, 0, buffer.Length);

【讨论】:

以上是关于使用多线程处理多个http请求HttpListener导致奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章

python里同时发送多个http请求怎么弄

httpd学习:http基础(续)

(05)使用DeferredResult多线程异步处理请求

(05)使用DeferredResult多线程异步处理请求

多线程 curl 同时处理多个连接

Http多线程版本