private /*async ValueTask*/ void OnReceiveMessage(BytesSegment frame, bool isEnd) { if (!isEnd) { if (pending != null) { pending.Append(frame); } pending = frame; } else { //检查有没有前面的消息帧 if (pending != null) { pending.Append(frame); pending = null; } //开始读取消息标识并从挂起请求中查找 var msgId = ReadMsgIdFromResponse(frame.First); if (waits.TryGetValue(msgId, out PooledTaskSource <object> tcs)) { tcs.SetResult(frame); //注意为最后一包 } else { BytesSegment.ReturnAll(frame.First); } } }
/// <summary> /// 归还缓存块 /// </summary> /// <remarks> /// 1.客户端调用系统服务后; /// 2.客户端转发调用至子进程后; /// 3.子进程调用转发的请求后. /// </remarks> internal void ReturnBuffer() { if (Count == FromWebSocket) { Debug.Assert(Arg1.ObjectValue != null); BytesSegment.ReturnAll((BytesSegment)Arg1.ObjectValue); } }
private async Task SendInvokeResponse(int msgId, AnyValue res) { if (res.Type == AnyValueType.Object && res.ObjectValue is BytesSegment) { var cur = (ReadOnlySequenceSegment <byte>)res.ObjectValue; await sendLock.WaitAsync(); try { while (cur != null && socket.State == WebSocketState.Open) { await socket.SendAsync(cur.Memory, WebSocketMessageType.Text, cur.Next == null, CancellationToken.None); cur = cur.Next; } } catch (Exception ex) { Log.Warn($"Send InvokeResponse to websocket error: {ex.Message}"); } finally { sendLock.Release(); BytesSegment.ReturnAll((BytesSegment)res.ObjectValue); //注意归还缓存块 } } else { byte[] data = null; bool serializeError = false; using (var ms = new MemoryStream(512)) //TODO: 暂用MemoryStream,待用BytesSegmentWriteStream替代 { res.SerializeAsInvokeResponse(ms, msgId); //TODO:处理异常 data = ms.ToArray(); } if (!serializeError && socket.State == WebSocketState.Open) { //注意:如果用WebSocketFrameWriteStream实现,待实现发送队列 await sendLock.WaitAsync(); try { await socket.SendAsync(data.AsMemory(), WebSocketMessageType.Text, true, CancellationToken.None); } finally { sendLock.Release(); } } } }
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 <TResult> InvokeAsync <TResult>(string service, string args) { if (socket.State != WebSocketState.Open) { //if (socket.State != WebSocketState.Connecting) // await ConnectAndStartReceiveAsync(); //尝试重新连接 throw new Exception("Connection is not open"); } var msgId = Interlocked.Increment(ref msgIndex); var require = $"{{\"I\":{msgId},\"S\":\"{service}\",\"A\":{args}}}"; var requireData = System.Text.Encoding.UTF8.GetBytes(require); await socket.SendAsync(requireData, WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false); var tcs = waitPool.Allocate(); lock (waits) { waits.Add(msgId, tcs); } var lastFrame = (BytesSegment)await tcs.WaitAsync(); lock (waits) { waits.Remove(msgId); } waitPool.Free(tcs); //反序列化结果 InvokeResult <TResult> res; try { res = Deserialize <InvokeResult <TResult> >(lastFrame); } finally { BytesSegment.ReturnAll(lastFrame.First); } if (!string.IsNullOrEmpty(res.E)) { throw new Exception(res.E); } return(res.D); }
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:序列化错误处理 } }