예제 #1
0
        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);
            });
        }
예제 #2
0
        public void ReadArgsTest1()
        {
            var js   = "\"A\":[4, \"2660935927-4\", \"HelloService\"]";
            var data = System.Text.Encoding.UTF8.GetBytes(js);

            var segment = BytesSegment.Rent();

            //data.AsSpan(4).CopyTo(segment.Buffer.AsSpan());
            //segment.Length = data.Length - 4;
            //Assert.Equal(System.Text.Encoding.UTF8.GetString(segment.Memory.Span),
            //    "[4, \"2660935927-4\", \"HelloService\"]");
            data.AsSpan().CopyTo(segment.Buffer);
            segment.Length = data.Length;

            var args = InvokeArgs.From(segment, 4);

            Assert.True(args.GetInt32() == 4);
            Assert.True(args.GetString() == "2660935927-4");
            Assert.True(args.GetString() == "HelloService");
        }
예제 #3
0
        public void ReadObject(BinSerializer bs)
        {
            Source   = (InvokeSource)bs.ReadByte();
            Protocol = (InvokeProtocol)bs.ReadByte();
            long hv = 0;

            unsafe
            {
                var span = new Span <byte>(&hv, 8);
                bs.Stream.Read(span);
            }
            WaitHandle = new IntPtr(hv);

            if (Protocol == InvokeProtocol.Bin)
            {
                SourceMsgId = bs.ReadInt32();
                Error       = (InvokeResponseError)bs.ReadByte();
                var temp = new AnyValue();
                temp.ReadObject(bs);
                Result = temp; //Don't use Result.ReadObject(bs)
            }
            else
            {
                //注意将子进程已序列化的结果读到缓存块内,缓存块由相应的通道处理并归还
                var          stream = (MessageReadStream)bs.Stream;
                BytesSegment cur    = null;
                int          len;
                while (stream.HasData)
                {
                    var temp = BytesSegment.Rent();
                    len         = bs.Stream.Read(temp.Buffer.AsSpan());
                    temp.Length = len;
                    if (cur != null)
                    {
                        cur.Append(temp);
                    }
                    cur = temp;
                }
                Result = AnyValue.From(cur.First);
            }
        }
예제 #4
0
        public void ReadArgsTest2()
        {
            var mockRunntimeContext = new MockRuntimeContext();

            Runtime.RuntimeContext.Init(mockRunntimeContext, 10410);
            mockRunntimeContext.AddModel(TestHelper.EmploeeModel);

            var js   = "\"A\":[{\"$T\":\"111428632783249997828\",\"Id\":\"01200000-0020-016e-fa64-547f10410001\",\"Name\":\"Sales Dept\"},\"01200000-0020-016e-fa64-547f10410001\"]";
            var data = System.Text.Encoding.UTF8.GetBytes(js);

            var segment = BytesSegment.Rent();

            data.AsSpan().CopyTo(segment.Buffer);
            segment.Length = data.Length;

            var args = InvokeArgs.From(segment, 4);
            var obj  = args.GetObject();

            Assert.True(obj != null);
            var id = args.GetGuid();

            Assert.True(id == Guid.Parse("01200000-0020-016e-fa64-547f10410001"));
        }
예제 #5
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:序列化错误处理
            }
        }
예제 #6
0
        //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));
        }