예제 #1
0
        public WebSocketClient(
            Uri url,
            WebSocketMessageSender sender       = null,
            ReceiverMemoryConfig receiverConfig = null,
            ILogger logger                       = null,
            string name                          = "CLIENT",
            Encoding messageEncoding             = null,
            Func <ClientWebSocket> clientFactory = null)
        {
            if (!ValidationUtils.ValidateInput(url))
            {
                throw new ArgumentNullException(nameof(url));
            }

            Url             = url;
            Name            = name;
            _logger         = logger;
            MessageEncoding = messageEncoding ?? Encoding.UTF8;

            receiverConfig = receiverConfig ?? ReceiverMemoryConfig.Default; //cannot use =?? in unity
            _memoryPool    = new MemoryPool(receiverConfig.InitialMemorySize, receiverConfig.MarginSize, logger);

            _clientFactory = clientFactory ?? DefaultClientFactory;

            _webSocketMessageSender = sender?.AsCore() ?? new SingleQueueSenderCore();
            _webSocketMessageSender.SetConfig(MessageEncoding, logger, Name);

            _webSocketMessageSender
            .ExceptionHappenedInSending
            .Subscribe(x =>
            {
                _backgroundExceptionQueue.Enqueue(x);
                Dispose();
            });
        }
예제 #2
0
        public WebSocketClient(
            WebSocket connectedSocket,
            WebSocketMessageSender sender       = null,
            ReceiverMemoryConfig receiverConfig = null,
            ILogger logger           = null,
            string name              = "CLIENT",
            Encoding messageEncoding = null)
        {
            _socket = connectedSocket ?? throw new ArgumentNullException(nameof(connectedSocket));

            Url            = null;
            _clientFactory = null;

            Name            = name;
            _logger         = logger;
            MessageEncoding = messageEncoding ?? Encoding.UTF8;

            receiverConfig = receiverConfig ?? ReceiverMemoryConfig.Default;
            _memoryPool    = new MemoryPool(receiverConfig.InitialMemorySize, receiverConfig.MarginSize, logger);

            _webSocketMessageSender = sender?.AsCore() ?? new SingleQueueSenderCore();
            _webSocketMessageSender.SetConfig(MessageEncoding, logger, Name);

            _webSocketMessageSender
            .ExceptionHappenedInSending
            .Subscribe(x =>
            {
                _backgroundExceptionQueue.Enqueue(x);
                Dispose();
            });
        }
예제 #3
0
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            try
            {
                if (_serverIsRunning)
                {
                    if (context.Request.Path == "/micro/ws" && context.WebSockets.IsWebSocketRequest)
                    {
                        var socket = await context.WebSockets.AcceptWebSocketAsync();

                        var completion = new TaskCompletionSource <object>();

                        var client = new WebSocketClient(socket, _loggerFactory, completion);

                        client.OnClose   += (key, websocket) => Clients.TryRemove(key, out _);
                        client.OnReceive += async buffer =>
                        {
                            var sender = new WebSocketMessageSender(client.Socket, _messageCodec, _address.Gzip);
                            try
                            {
                                var invokeMessage =
                                    await _messageCodec.DecodeAsync <InvokeMessage>(buffer, _address.Gzip);

                                await _listener.OnReceived(sender, invokeMessage);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, $"接收消息异常:{ex.Message}");
                            }
                        };
                        Clients.TryAdd(client.SocketId, client);
                        _logger.LogInformation($"Socket {client.SocketId}: New connection.");

                        // TaskCompletionSource<> is used to keep the middleware pipeline alive;
                        // SocketProcessingLoop calls TrySetResult upon socket termination
                        _ = Task.Run(() => client.ReceiveAsync(SocketLoopTokenSource.Token).ConfigureAwait(false));
                        await completion.Task;
                    }
                }
                else
                {
                    context.Response.StatusCode = 409;
                }
            }
            catch (Exception ex)
            {
                // HTTP 500 Internal server error
                context.Response.StatusCode = 500;
                //Program.ReportException(ex);
            }
            finally
            {
                // if this middleware didn't handle the request, pass it on
                if (!context.Response.HasStarted)
                {
                    await next(context);
                }
            }
        }
예제 #4
0
        protected override async Task <IMicroClient> Create(ServiceAddress address)
        {
            var listener  = new MessageListener();
            var webSocket = new ClientWebSocket();
            var uri       = new Uri(new Uri(address.ToString()), "/micro/ws");
            await webSocket.ConnectAsync(uri, CancellationToken.None);

            var codec  = Provider.GetClientCodec(address.Codec);
            var sender = new WebSocketMessageSender(webSocket, codec, address.Gzip);

            var completion   = new TaskCompletionSource <object>();
            var socketClient = new WebSocketClient(webSocket, LoggerFactory, completion);

            socketClient.OnReceive += async buffer =>
            {
                var resultMessage = await codec.DecodeAsync <MessageResult>(buffer, address.Gzip);

                await listener.OnReceived(sender, resultMessage);
            };
            socketClient.OnClose += (key, socket) => Remove(address);

            _ = Task.Run(() => socketClient.ReceiveAsync(CancellationToken.None).ConfigureAwait(false));
            return(new MicroClient(sender, listener, MicroExecutor, LoggerFactory));
        }