예제 #1
0
        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);
                }
            }
        }
예제 #2
0
 /// <summary>
 /// 归还缓存块
 /// </summary>
 /// <remarks>
 /// 1.客户端调用系统服务后;
 /// 2.客户端转发调用至子进程后;
 /// 3.子进程调用转发的请求后.
 /// </remarks>
 internal void ReturnBuffer()
 {
     if (Count == FromWebSocket)
     {
         Debug.Assert(Arg1.ObjectValue != null);
         BytesSegment.ReturnAll((BytesSegment)Arg1.ObjectValue);
     }
 }
예제 #3
0
        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();
                    }
                }
            }
        }
예제 #4
0
        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
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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:序列化错误处理
            }
        }