Пример #1
0
    internal async Task Acceptor(HttpContext context, Func <Task> next)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            return;
        }

        string token = context.Request.Query["token"];

        if (string.IsNullOrEmpty(token))
        {
            return;
        }
        var token_value = await _redis.GetAsync($"{_redisPrefix}Token{token}");

        if (string.IsNullOrEmpty(token_value))
        {
            throw new Exception("授权错误:用户需通过 ImHelper.PrevConnectServer 获得包含 token 的连接");
        }

        var data = JsonConvert.DeserializeObject <(Guid clientId, string clientMetaData)>(token_value);

        var socket = await context.WebSockets.AcceptWebSocketAsync();

        var cli   = new ImServerClient(socket, data.clientId);
        var newid = Guid.NewGuid();

        var wslist = _clients.GetOrAdd(data.clientId, cliid => new ConcurrentDictionary <Guid, ImServerClient>());

        wslist.TryAdd(newid, cli);
        _redis.StartPipe(a => a.HIncrBy($"{_redisPrefix}Online", data.clientId.ToString(), 1).Publish($"evt_{_redisPrefix}Online", token_value));

        var buffer = new byte[BufferSize];
        var seg    = new ArraySegment <byte>(buffer);

        try
        {
            while (socket.State == WebSocketState.Open && _clients.ContainsKey(data.clientId))
            {
                var incoming = await socket.ReceiveAsync(seg, CancellationToken.None);

                var outgoing = new ArraySegment <byte>(buffer, 0, incoming.Count);
            }
            socket.Abort();
        }
        catch
        {
        }
        wslist.TryRemove(newid, out var oldcli);
        if (wslist.Any() == false)
        {
            _clients.TryRemove(data.clientId, out var oldwslist);
        }
        await _redis.EvalAsync($"if redis.call('HINCRBY', KEYS[1], '{data.clientId}', '-1') <= 0 then redis.call('HDEL', KEYS[1], '{data.clientId}') end return 1",
                               $"{_redisPrefix}Online");

        LeaveChan(data.clientId, GetChanListByClientId(data.clientId));
        await _redis.PublishAsync($"evt_{_redisPrefix}Offline", token_value);
    }
Пример #2
0
    /// <summary>
    /// websocket中间件
    /// </summary>
    /// <param name="context"></param>
    /// <param name="next"></param>
    /// <returns></returns>
    internal async Task Acceptor(HttpContext context, Func <Task> next)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            return;
        }

        string token = context.Request.Query["token"];

        if (string.IsNullOrEmpty(token))
        {
            return;
        }

        var cacheKey    = $"{_redisPrefix}Token{token}";
        var token_value = _redis.Get(cacheKey);

        if (string.IsNullOrEmpty(token_value))
        {
            throw new Exception("授权错误:用户需通过 ImHelper.PrevConnectServer 获得包含 token 的连接");
        }

        var(clientId, clientMetaData) = JsonConvert.DeserializeObject <(string clientId, string clientMetaData)>(token_value);

        CancellationToken ct = context.RequestAborted;
        var socket           = await context.WebSockets.AcceptWebSocketAsync();

        var cli   = new ImServerClient(socket, clientId);
        var newid = Guid.NewGuid().ToString();

        var wslist = _clients.GetOrAdd(clientId, cliid => new ConcurrentDictionary <string, ImServerClient>());

        wslist.TryAdd(newid, cli);
        using (var pipe = _redis.StartPipe())
        {
            pipe.HIncrBy($"{_redisPrefix}Online", clientId.ToString(), 1);
            pipe.Publish($"evt_{_redisPrefix}Online", token_value);
            pipe.EndPipe();
        }

        var buffer = new byte[BufferSize];
        var seg    = new ArraySegment <byte>(buffer);

        try
        {
            while (socket.State == WebSocketState.Open && _clients.ContainsKey(clientId))
            {
                var res      = string.Empty;
                var incoming = await socket.ReceiveAsync(seg, CancellationToken.None);

                using (var ms = new MemoryStream())
                {
                    do
                    {
                        ms.Write(seg.Array, seg.Offset, incoming.Count);
                    }while (!incoming.EndOfMessage);

                    ms.Seek(0, SeekOrigin.Begin);
                    if (incoming.MessageType == WebSocketMessageType.Text)
                    {
                        using (var reader = new StreamReader(ms, Encoding.UTF8))
                        {
                            res = await reader.ReadToEndAsync();

                            ProcessResponse(res);
                        }
                    }
                }
                var outgoing = new ArraySegment <byte>(buffer, 0, incoming.Count);
            }
            socket.Abort();
        }
        catch (Exception ex)
        {
            Log.Error($"Socket异常:{ex.Message}");
        }
        wslist.TryRemove(newid, out var oldcli);
        if (wslist.Any() == false)
        {
            _clients.TryRemove(clientId, out var oldwslist);
        }
        _redis.Eval($"if redis.call('HINCRBY', KEYS[1], '{clientId}', '-1') <= 0 then redis.call('HDEL', KEYS[1], '{clientId}') end return 1", new[] { $"{_redisPrefix}Online" });
        LeaveChan(clientId, GetChanListByClientId(clientId));
    }
Пример #3
0
    internal async Task Acceptor(HttpContext context, Func <Task> next)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            return;
        }

        string token = context.Request.Query["token"];

        if (string.IsNullOrEmpty(token))
        {
            return;
        }
        var token_value = _redis.Get($"{_redisPrefix}Token{token}");

        if (string.IsNullOrEmpty(token_value))
        {
            throw new Exception("授权错误:用户需通过 ImHelper.PrevConnectServer 获得包含 token 的连接");
        }
        var data = JsonConvert.DeserializeObject <(string clientId, string clientMetaData)>(token_value);

        CancellationToken ct = context.RequestAborted;
        var socket           = await context.WebSockets.AcceptWebSocketAsync();

        var cli   = new ImServerClient(socket, data.clientId);
        var newid = Guid.NewGuid().ToString();

        var wslist = _clients.GetOrAdd(data.clientId, cliid => new ConcurrentDictionary <string, ImServerClient>());

        wslist.TryAdd(newid, cli);
        using (var pipe = _redis.StartPipe())
        {
            pipe.HIncrBy($"{_redisPrefix}Online", data.clientId.ToString(), 1);
            pipe.Publish($"evt_{_redisPrefix}Online", token_value);
            pipe.EndPipe();
        }

        var buffer = new byte[BufferSize];
        var seg    = new ArraySegment <byte>(buffer);

        try
        {
            while (socket.State == WebSocketState.Open && _clients.ContainsKey(data.clientId))
            {
                if (ct.IsCancellationRequested)
                {
                    break;
                }
                string response = await ReceiveStringAsync(socket, ct);

                if (string.IsNullOrEmpty(response))
                {
                    continue;
                }
                MsgTemplate msg = null;
                try
                {
                    msg = JsonConvert.DeserializeObject <MsgTemplate>(response);
                    ImServerClient currentSocket = wslist.Values.First(u => u.clientId == msg.clientId);
                    if (currentSocket == null)
                    {
                        continue;
                    }
                    if (msg.type == "ping")
                    {
                        if (msg.currentSence == 0)
                        {
                            await SendStringAsync(currentSocket.socket, JsonConvert.SerializeObject(msg), ct);
                        }
                        else if (msg.currentSence == 1)
                        {
                            await _redis.SetAsync($"KEY_IM_DOCITOR_CONNECTION_SESSION:{msg.clientId}", msg.connectionBatchCode, 3);
                        }
                    }
                }
                catch
                {
                }
            }
            socket.Abort();
            //await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);
            //socket.Dispose();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Socket异常:{ex.Message}");
        }
        wslist.TryRemove(newid, out var oldcli);
        if (wslist.Any() == false)
        {
            _clients.TryRemove(data.clientId, out var oldwslist);
        }
        _redis.Eval($"if redis.call('HINCRBY', KEYS[1], '{data.clientId}', '-1') <= 0 then redis.call('HDEL', KEYS[1], '{data.clientId}') end return 1", new[] { $"{_redisPrefix}Online" });
        LeaveChan(data.clientId, GetChanListByClientId(data.clientId));
        //_redis.Publish($"evt_{_redisPrefix}Offline", token_value);
    }