internal async Task SendAsync(GatewayPayload payload, bool highPriority, WebSocketMessageType msgType, CancellationToken cts) // TODO : заменить CTS на Action { Console.WriteLine($"Sending: {payload.Opcode}"); payload.Sequence = lastSequence; string jsonPayload = JsonConvert.SerializeObject(payload, typeof(GatewayPayload), null); // TODO : сериализацию с помощью внещнего проекта byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonPayload); byte chunksCount = 0; for (int dataLength = jsonBytes.Length; dataLength > 0; dataLength -= chunkSize) { chunksCount++; } PayloadRecovery recovery = new PayloadRecovery(payload, highPriority, msgType); try { using (SocketAccessToken token = highPriority ? socketHelper.GetHighPrioritySendAccess() : socketHelper.GetSendAccess()) { token.OnCancellation(x => ResendPayloadAsync(x), recovery); // TODO : проверить на работоспособность if (chunksCount == 1) { await socket.SendAsync(new ArraySegment <byte>(jsonBytes), msgType, true, token.CancellationToken); } else { for (int i = 0; i < chunksCount; i++) { bool isLastMsg = i == chunksCount; int offset = i * chunkSize, count = isLastMsg ? (jsonBytes.Length - chunkSize * i) : chunkSize; await socket.SendAsync(new ArraySegment <byte>(jsonBytes, offset, count), msgType, isLastMsg, token.CancellationToken); } } } } catch (OperationCanceledException ex) { // TODO : логирование return; } catch (WebSocketException ex) { Reconnect(); return; } Interlocked.Increment(ref payloadSentLastMinute); }
private async void ListenToSocket() { byte[] buffer = new byte[chunkSize]; int capacity = 256; // TODO : изначальный размер буффера StringBuilder jsonResultBuilder = new StringBuilder(capacity); WebSocketReceiveResult result = null; while (true) //TAI : проверить разность быстродействия при обнулении буффера и без обнуления { //buffer = new byte[chunkSize]; //TAI : нужно ли здесь обнуление? jsonResultBuilder.Clear(); jsonResultBuilder.Capacity = CalculateJsonBuilderCapacity(jsonResultBuilder.Length); try { using (SocketAccessToken token = socketHelper.GetReceiveAccess()) { result = await socket.ReceiveAsync(new ArraySegment <byte>(buffer), token.CancellationToken) .ConfigureAwait(false); jsonResultBuilder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); while (!result.EndOfMessage) { //buffer = new byte[chunkSize]; //TAI : нужно ли здесь обнуление? result = await socket.ReceiveAsync(new ArraySegment <byte>(buffer), token.CancellationToken) .ConfigureAwait(false); jsonResultBuilder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); } } } catch (OperationCanceledException ex) { // TODO : инструмент логирования continue; } catch (WebSocketException ex) { // TODO : инструмент логирования Reconnect(); // TODO: здесь отправляется двойной резюм continue; } if (result.MessageType == WebSocketMessageType.Close) { SocketCloseReceived(result.CloseStatus, result.CloseStatusDescription); // TODO : эта херня работает не так как нужно } else { #pragma warning disable 4014 // Fire and forget string payload = jsonResultBuilder.ToString(); Task.Factory.StartNew(() => NewPayloadReceived(payload)) .ConfigureAwait(false); } } }
internal virtual void Release(SocketAccessToken token) { if (token.type == AccessType.Send) { sender.Release(); } else { reciever.Release(); } }