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); }
/// <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)); }
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); }