C#编写本地端口拦截代理时WebSocket连接进入aborted状态求解
问题原因分析
- 请求获取逻辑错误:
FakeDevice方法仅在进入循环前调用了一次listener.GetContext(),后续循环一直在重复处理同一个请求上下文,没有处理新的连接请求。 async void滥用:FakeDevice和Process方法都用了async void返回值,这类方法仅适用于事件处理器,普通异步方法使用async void会导致调用方无法等待异步执行流程,异常也无法正常捕获,Main方法调用FakeDevice后没有等待逻辑,程序可能直接退出。- 连接建立后直接返回:第一次收到WebSocket请求、完成
AcceptWebSocketAsync握手后,代码直接return,后续的收发逻辑完全没有执行,浏览器端连接因为长时间没有后续交互被强制中断。 - 全局WebSocket上下文共享错误:将
WebSocketContext设为静态全局变量,仅能处理单个连接,且新连接进来后会直接复用旧连接的上下文,逻辑完全不符合代理多连接处理要求。 - 同步方法阻塞:使用同步的
listener.GetContext()会阻塞线程,应该搭配异步方法GetContextAsync()使用。
修正后参考代码
class Program { static async Task Main(string[] args) { await FakeDevice(); } protected async static Task FakeDevice() { HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://localhost:4033/"); listener.Start(); Console.WriteLine("服务已启动,监听端口4033"); while (listener.IsListening) { // 每次循环获取新的请求上下文 var context = await listener.GetContextAsync(); // 每个连接单独开异步处理,不阻塞后续请求接收 _ = Process(context); } } protected async static Task Process(HttpListenerContext context) { if (context.Request.IsWebSocketRequest) { WebSocketContext wsContext = null; try { // 完成WebSocket握手 wsContext = await context.AcceptWebSocketAsync(subProtocol: null); var socket = wsContext.WebSocket; byte[] receiveBuffer = new byte[1024]; while (socket.State == WebSocketState.Open) { WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); } else { // 这里当前是回显逻辑,可后续修改为代理转发逻辑 await socket.SendAsync(new ArraySegment<byte>(receiveBuffer, 0, receiveResult.Count), receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None); } } } catch (Exception e) { Console.WriteLine($"连接处理异常: {e.Message}"); } finally { wsContext?.WebSocket.Dispose(); } } else { // 非WebSocket请求返回400 context.Response.StatusCode = 400; context.Response.Close(); Console.WriteLine("收到非WebSocket请求"); } } }
内容的提问来源于stack exchange,提问作者szpic
相关产品推荐
相关产品推荐

