// Endless Start reading loop private async void StartReading(Socket client) { var endpoint = client.RemoteEndPoint as IPEndPoint; // Get remote endpoint // Loop theoretically infinetly while (true) { try { long size = await LeadingByteProcessor.ReadLeading(client).ConfigureAwait(false); // leading byte[] bytes = new byte[size]; ArraySegment <byte> segment = new ArraySegment <byte>(bytes); //TODO: Do something when receiving interrupts? Wait for client to come back? // read until all data is read int read = 0; while (read < size) { long receive = size - read; // current buffer size if (receive > ReceiveBufferSize) { receive = ReceiveBufferSize; // max size } ArraySegment <byte> slice = segment.SliceEx(read, (int)receive); // get buffered portion of array read += await client.ReceiveAsync(slice, SocketFlags.None).ConfigureAwait(false); } if (read < 1) { throw new TransferException($"{read} bytes were read! " + "Null bytes could mean a connection shutdown."); } var message = ZeroFormatterSerializer.Deserialize <T>(segment.Array); ReceivedMessage?.Invoke(endpoint, message); // call event } catch (SocketException ex) { Console.WriteLine(ex.ErrorCode); bool success = DisconnectClient(endpoint); // try to disconnect if (success) // Exit Reading loop once successfully disconnected { return; } } catch (TransferException) { // 0 read bytes = null byte bool success = DisconnectClient(endpoint); // try to disconnect if (success) { return; // Exit Reading loop once successfully disconnected } } } // Listen again after client connected }
public async Task Send(T message) { if (message.Equals(default(T))) { throw new ArgumentNullException(nameof(message)); } bool alive = Socket.Ping(); if (!alive) { throw new TransferException($"The Socket to {EndPoint} is not responding!"); } try { // build byte[] out of message (serialize with ZeroFormatter) var bytes = ZeroFormatterSerializer.Serialize(message); var segment = new ArraySegment <byte>(bytes); int size = bytes.Length; await LeadingByteProcessor.SendLeading(Socket, size) .ConfigureAwait(false); // Send receiver the byte count //TODO: Decide whether to catch errors in buffer-loop and continue once fixed or cancel whole send? int written = 0; while (written < size) { int send = size - written; // current buffer size if (send > SendBufferSize) { send = SendBufferSize; // max size } var slice = segment.SliceEx(written, send); // buffered portion of array written = await Socket.SendAsync(slice, SocketFlags.None).ConfigureAwait(false); } if (written < 1) { throw new TransferException($"{written} bytes were sent! " + "Null bytes could mean a connection shutdown."); } } catch (SocketException) { ConnectionLost?.Invoke(EndPoint); // On any error - cancel whole buffered writing if (AutoReconnect) { await Reconnect().ConfigureAwait(false); // Try reconnecting and re-send everything once reconnected } else { throw; // Throw if we're not trying to reconnect } } }
// Endless Start reading loop private void StartReceiving() { // Loop theoretically infinetly while (true) { try { // Read the leading "byte" long size = LeadingByteProcessor.ReadLeading(Socket).GetAwaiter().GetResult(); byte[] bytes = new byte[size]; ArraySegment <byte> segment = new ArraySegment <byte>(bytes); //TODO: Decide whether to catch errors in buffer-loop and continue once fixed or cancel whole receive? // read until all data is read int read = 0; while (read < size) { long receive = size - read; // current buffer size if (receive > ReceiveBufferSize) { receive = ReceiveBufferSize; // max size } ArraySegment <byte> slice = segment.SliceEx(read, (int)receive); // get buffered portion of array read += Socket.ReceiveAsync(slice, SocketFlags.None).GetAwaiter().GetResult(); } var message = ZeroFormatterSerializer.Deserialize <T>(segment.Array); ReceivedMessage?.Invoke(EndPoint, message); // call event } catch (ObjectDisposedException) { return; // Socket was closed & disposed -> exit } catch (SocketException) { ConnectionLost?.Invoke(EndPoint); if (!AutoReconnect) { Reconnect().GetAwaiter().GetResult(); // Try reconnecting on an error, then continue receiving } } // Listen again after client connected } }
public async Task Send(T message, IPEndPoint to) { if (message.Equals(default(T))) { throw new ArgumentNullException(nameof(message)); } // Build a byte array of the serialized data byte[] bytes = ZeroFormatterSerializer.Serialize(message); ArraySegment <byte> segment = new ArraySegment <byte>(bytes); // Find socket var socket = Sockets.FirstOrDefault(c => c.Key.Equals(to)).Value; if (socket == null) { throw new NetworkInterfaceException($"The IP Address {to} could not be found!"); } int size = bytes.Length; await LeadingByteProcessor.SendLeading(socket, size).ConfigureAwait(false); // send leading size //TODO: Do something when sending interrupts? Wait for client to come back? // Write buffered int written = 0; while (written < size) { int send = size - written; // current buffer size if (send > SendBufferSize) { send = SendBufferSize; // max size } ArraySegment <byte> slice = segment.SliceEx(written, send); // buffered portion of array written = await socket.SendAsync(slice, SocketFlags.None).ConfigureAwait(false); } if (written < 1) { throw new TransferException($"{written} bytes were sent! " + "Null bytes could mean a connection shutdown."); } }