private void StartReceiveAsync() { Task.Run(async() => { ValueWebSocketReceiveResult result; BytesSegment frame; do { frame = BytesSegment.Rent(); try { result = await socket.ReceiveAsync(frame.Buffer.AsMemory(), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { BytesSegment.ReturnOne(frame); break; } } catch (Exception ex) { BytesSegment.ReturnOne(frame); Console.WriteLine($"WebSocket receive error: {ex.Message}"); //TODO:考虑开始重新连接 break; } frame.Length = result.Count; OnReceiveMessage(frame, result.EndOfMessage); //不需要捕获异常 } while (true); }); }
internal async ValueTask OnReceiveMessage(BytesSegment frame, bool isEnd) { if (!isEnd) { if (pending != null) { pending.Append(frame); } pending = frame; } else { //检查有没有前面的消息帧 if (pending != null) { pending.Append(frame); pending = null; } //开始读取消息 int msgId = 0; string service = null; //TODO:优化不创建string int offset = 0; //偏移量至参数数组开始,不包含[Token Exception requireError = null; try { offset = InvokeHelper.ReadRequireHead(frame.First, ref msgId, ref service); if (offset == -1) //没有参数 { BytesSegment.ReturnOne(frame); } } catch (Exception ex) { requireError = ex; BytesSegment.ReturnAll(frame); //读消息头异常归还缓存块 } if (requireError != null) { Log.Warn(string.Format("收到无效的Api调用请求: {0}", requireError.Message)); await SendInvokeResponse(msgId, AnyValue.From(requireError)); return; } _ = ProcessInvokeRequire(msgId, service, frame, offset); //no need await } }
public async Task Invoke(HttpContext context) { //暂简单处理,读请求数据至缓存块,然后走与WebSocket相同的流程 //待实现Utf8JsonReaderStream后再修改 int bytesRead = 0; int totalBytes = (int)context.Request.ContentLength.Value; BytesSegment frame = null; while (bytesRead < totalBytes) //TODO:读错误归还缓存块 { var temp = BytesSegment.Rent(); int len = await context.Request.Body.ReadAsync(temp.Buffer.AsMemory()); temp.Length = len; bytesRead += len; if (frame != null) { frame.Append(temp); } frame = temp; } //1. 解析请求头 int msgId = 0; string service = null; //TODO:优化不创建string int offset = 0; //偏移量至参数数组开始,不包含[Token AnyValue res = AnyValue.Empty; try { offset = InvokeHelper.ReadRequireHead(frame.First, ref msgId, ref service); if (offset == -1) //没有参数 { BytesSegment.ReturnOne(frame); } } catch (Exception ex) { res = AnyValue.From(ex); BytesSegment.ReturnAll(frame); //读消息头异常归还缓存块 Log.Warn($"收到无效的Api调用请求: {ex.Message}\n{ex.StackTrace}"); } //2. 设置当前会话并调用服务 if (res.ObjectValue == null) { var webSession = context.Session.LoadWebSession(); RuntimeContext.Current.CurrentSession = webSession; try { var hostCtx = (HostRuntimeContext)RuntimeContext.Current; res = await hostCtx.InvokeByClient(service, 0, InvokeArgs.From(frame, offset)); } catch (Exception ex) { Log.Warn($"调用服务异常: {ex.Message}\n{ex.StackTrace}"); res = AnyValue.From(ex); } } //3. 返回结果,注意:FileResult特殊类型统一由BlobController处理 context.Response.ContentType = "application/json"; if (res.Type == AnyValueType.Object && res.ObjectValue is BytesSegment) { var cur = (ReadOnlySequenceSegment <byte>)res.ObjectValue; try { while (cur != null) { await context.Response.Body.WriteAsync(cur.Memory); cur = cur.Next; } } catch (Exception ex) { Log.Warn($"Send InvokeResponse to ajax error: {ex.Message}"); } finally { BytesSegment.ReturnAll((BytesSegment)res.ObjectValue); //注意归还缓存块 } } else { res.SerializeAsInvokeResponse(context.Response.Body, 0);//TODO:序列化错误处理 } }
//TODO:use rwlock, 另想办法不需要此字典表 internal static async Task OnAccept(HttpContext context, WebSocket webSocket) { //验证是否是已登录用户 var webSession = context.Session.LoadWebSession(); Log.Debug($"接受WebSocket连接, {webSocket.GetType()} Session = {webSession}"); //TODO:没有Session即没有登录先则直接关闭连接 //加入至列表 var client = new WebSocketClient(webSocket, webSession); lock (clients) { clients.Add(webSession.SessionID, client); } //开始接收数据 ValueWebSocketReceiveResult result; BytesSegment frame; do { frame = BytesSegment.Rent(); try { result = await webSocket.ReceiveAsync(frame.Buffer.AsMemory(), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { BytesSegment.ReturnOne(frame); break; } } catch (Exception ex) { BytesSegment.ReturnOne(frame); Log.Warn($"WebSocket receive error: {ex.Message}"); break; } frame.Length = result.Count; await client.OnReceiveMessage(frame, result.EndOfMessage); //不需要捕获异常 } while (true); try { // await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } catch (Exception ex) { Log.Debug($"关闭WebSocket通道失败:{ex.Message},忽略继续"); } //移除清理 if (webSession != null) { webSession.Dispose(); } var leftCount = 0; lock (clients) { clients.Remove(webSession.SessionID); leftCount = clients.Count; } Log.Debug(string.Format("WebSocket关闭, 还余: {0}", leftCount)); }