public bool SendQuanta(byte[] data, Priority priority = Priority.Normal) { if (!IsReady) { return(false); } var ok = false; var ok2 = _sendActor.PostWait(() => { var compressedPacket = UseCompression ? GZipper.Zip(data) : data; var length = compressedPacket.Length; var header = StructMarshaller.ToByteArray( new MessageHeader { Length = length, DataIsCompressed = UseCompression }); var packet = new byte[length + header.Length]; Array.Copy(header, 0, packet, 0, header.Length); Array.Copy(compressedPacket, 0, packet, header.Length, length); var sent = 0; try { sent = Client.Client.Send(packet, length + header.Length, SocketFlags.None); } catch (Exception ex) { Stop(ex); } ok = sent == length + header.Length; }, priority); return(ok && ok2); }
private void beginReadLoop() { if (_reading) { return; } _reading = true; _readThread = new Thread(() => { while (_reading) { try { var headerSize = MessageHeader.HeaderSize; var headerBuffer = new byte[headerSize]; var read = 0; do { try { read = Client.Client.Receive(headerBuffer, headerSize, SocketFlags.None); if (read == 0) { throw new Exception("Error reading header. (Probably a graceful shutdown.)"); } if (read != headerSize) { throw new Exception( $"Error reading header. (Not enough data in header - required {headerSize} bytes, got {read} bytes.)"); } #if (DEBUGOUTPUT) Debug.WriteLine($"Read header {read}"); #endif PartialDataRead?.Invoke(this, read); } catch (SocketException sex) when(sex.SocketErrorCode == SocketError.TimedOut) { #if (DEBUGOUTPUT) Debug.WriteLine("Waiting for header."); #endif } } while (_reading && read < headerSize); var messageHeader = StructMarshaller.FromByteArray <MessageHeader>(headerBuffer); var packageSize = messageHeader.Length; #if (DEBUGOUTPUT) Debug.WriteLine($"Getting package size {packageSize}"); #endif var zeroReadCount = 0; var data = new byte[packageSize]; var position = 0; while (position < packageSize && _reading) { var toRead = Client.Client.Available; if (toRead + position > packageSize) { toRead = packageSize - position; } if (toRead > _maxChunkSize) { toRead = _maxChunkSize; } read = Client.Client.Receive(data, position, toRead, SocketFlags.None); if (read == 0) { zeroReadCount ++; //todo: this should be time based not count. first time you get zero bytes, if you don't get anything within ~1 second, the connection is dead. } else { zeroReadCount = 0; } if (zeroReadCount > _zeroReadLimit) { throw new Exception( $"Error reading data in '{_parent?.Name}'. (Probably a graceful shutdown or zero read limit reached)"); } position += read; PartialDataRead?.Invoke(this, read); } var uncompressedData = messageHeader.DataIsCompressed ? GZipper.Unzip(data) : data; _rcvActor.Post(() => QuantaReceived?.Invoke(this, uncompressedData)); } catch (Exception ex) { #if (DEBUGOUTPUT) Debug.WriteLine($"Stopping the byte quanta client because {ex.ToString()}"); #endif Stop(ex); return; } } Stop(); }) { IsBackground = true, Name = "Byte client reading thread" }; _readThread.Start(); }