private async Task DataReceiver(ClientMetadata client, CancellationToken?cancelToken = null) { var clientId = client.IpPort(); try { #region Wait-for-Data while (true) { cancelToken?.ThrowIfCancellationRequested(); byte[] data = await MessageReadAsync(client); if (data != null) { if (MessageReceived != null) { var _ = Task.Run(() => MessageReceived?.Invoke(client.IpPort(), data), CancellationToken.None); } } else { // no message available await Task.Delay(30, cancelToken.GetValueOrDefault()); } } #endregion } catch (OperationCanceledException oce) { Log("DataReceiver client " + clientId + " disconnected (canceled): " + oce.Message); } catch (WebSocketException wse) { Log("DataReceiver client " + clientId + " disconnected (websocket exception): " + wse.Message); } finally { if (RemoveClient(client)) { // must only fire disconnected event if the client was previously connected. Note that // multithreading gives multiple disconnection events from the socket, the reader and the writer ClientDisconnected?.Invoke(clientId); client.Ws.Dispose(); Log("DataReceiver client " + clientId + " disconnected (now " + _Clients.Count + " clients active)"); } } }
private async Task <bool> MessageWriteAsync(ClientMetadata client, byte[] data, WebSocketMessageType messageType) { try { #region Send-Message // Cannot have two simultaneous SendAsync calls so use a // semaphore to block the second until the first has completed await client.SendAsyncLock.WaitAsync(client.KillToken.Token); try { await client.Ws.SendAsync(new ArraySegment <byte>(data, 0, data.Length), messageType, true, client.KillToken.Token); } finally { client.SendAsyncLock.Release(); } return(true); #endregion } catch (Exception e) { Log("*** MessageWriteAsync " + client.IpPort() + " disconnected due to exception " + e); return(false); } }
private bool RemoveClient(ClientMetadata client) { return(_Clients.TryRemove(client.IpPort(), out var removedClient)); }
private bool AddClient(ClientMetadata client) { _Clients.TryRemove(client.IpPort(), out var removedClient); return(_Clients.TryAdd(client.IpPort(), client)); }