You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HttpListener应用处理首个请求后关闭,如何实现永久处理请求?

解决HttpListener处理完第一个请求就关闭的问题

你的代码核心问题是:RunWebHookSubscription方法仅调用了一次GetContextAsync,处理完第一个请求后方法执行完毕,程序自然退出。要实现永久处理请求,需要循环监听请求,同时异步处理每个请求以避免阻塞主线程。

修改后的完整代码

await main.RunWebHookSubscription();

public async Task RunWebHookSubscription(CancellationToken cancellationToken = default)
{
    Console.WriteLine("Hook waiting");

    using HttpListener listener = new HttpListener();
    listener.Prefixes.Add("http://localhost:8080/hook/");
    listener.Start();

    try
    {
        // 循环监听请求,直到收到取消信号或程序终止
        while (!cancellationToken.IsCancellationRequested)
        {
            // 异步获取请求上下文,不阻塞循环
            HttpListenerContext context = await listener.GetContextAsync();
            // 异步处理请求,单独捕获异常避免影响整个监听服务
            _ = HandleRequestAsyncRun(context).ContinueWith(t => 
            {
                if (t.Exception != null)
                {
                    Console.WriteLine($"处理请求出错: {t.Exception.Message}");
                }
            }, TaskContinuationOptions.OnlyOnFaulted);
        }
    }
    finally
    {
        listener.Stop();
        Console.WriteLine("Hook已停止");
    }
}

async Task HandleRequestAsyncRun(HttpListenerContext context)
{
    try
    {
        var request = context.Request;
        var body = WebHookRequestHadler(request);
        Console.WriteLine(body);
        
        if (!string.IsNullOrEmpty(body))
        {
            var eventData = JsonSerializer.Deserialize<WebHookEventData>(body);
            // TODO: 调用业务方法处理事件
        }

        // 返回成功响应,避免客户端超时
        var response = context.Response;
        response.StatusCode = 200;
        response.ContentType = "application/json";
        using var writer = new StreamWriter(response.OutputStream);
        await writer.WriteAsync("{\"status\":\"success\"}");
        response.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"处理请求异常: {ex.ToString()}");
        // 返回错误响应
        var response = context.Response;
        response.StatusCode = 500;
        response.ContentType = "application/json";
        using var writer = new StreamWriter(response.OutputStream);
        await writer.WriteAsync($"{{\"status\":\"error\",\"message\":\"{ex.Message}\"}}");
        response.Close();
    }
}

string WebHookRequestHadler(HttpListenerRequest request)
{
    if (!request.HasEntityBody)
    {
        return null;
    }
    using System.IO.Stream body = request.InputStream;
    using var reader = new System.IO.StreamReader(body, request.ContentEncoding);
    return reader.ReadToEnd();
}

关键修改说明

  • 循环监听:通过while循环持续调用GetContextAsync,确保服务一直等待新请求。
  • 异步处理请求:获取请求上下文后,异步执行处理逻辑,不阻塞下一次请求的监听,支持并发处理多个WebHook请求。
  • 异常隔离:在请求处理方法和异步任务中单独捕获异常,避免单个请求的错误导致整个监听服务崩溃。
  • 响应返回:补充了成功/错误响应的返回逻辑,符合WebHook规范,避免客户端长时间等待超时。
  • 资源管理:用using包裹HttpListener和流对象,确保资源能正确释放。

额外建议

  • 若需要优雅关闭服务,可以通过CancellationToken监听控制台终止信号(如Ctrl+C),触发循环退出。
  • 建议替换Console.WriteLine为专业日志框架(如Serilog、NLog),方便生产环境排查问题。
  • 增加WebHook请求签名验证逻辑,确保请求来源合法,防止恶意请求。

内容的提问来源于stack exchange,提问作者Dmitry Sokolov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:52:31