/// <summary> /// NB: this method is not thread-safe!!! /// a future enhancement /// </summary> /// <param name="ns"></param> /// <param name="message"></param> /// <returns></returns> private async Task SendAsync(NetworkStream ns, MessageBase message) { try { var data = message.ToBytes(); var wrappedData = PacketProtocol.WrapMessage(data); int index = 0; while (index < wrappedData.Length) { int packetSize = (wrappedData.Length - index) > options.TransportBufferSize ? options.TransportBufferSize : (wrappedData.Length - index); await ns.WriteAsync(wrappedData, index, packetSize); index += packetSize; } log.Trace($"Sent: {message.GetType().Name} ({data.Length} bytes)"); } catch (Exception xe) { log.LogError(xe.Message); //Debugger.Break(); throw; } }
/// <summary> /// Register a method to receive MessageBase derived messages on the give <see cref="System.Net.Sockets.TcpClient"/> /// </summary> /// <remarks> /// This is a method intended for use in a client to receive responses from the server. /// </remarks> /// <param name="client">A client obtained by calling <see cref="Connect"/></param> /// <param name="token">A cancellation token (required)</param> /// <param name="onMessageReceive">The method to call for each message received</param> /// <returns></returns> public async Task ReceiveAsync(TcpClient client, CancellationToken token, Action <MessageBase> onMessageReceive) { using (client) { var buffer = new byte[this.options.MaxMessageSize]; var stream = client.GetStream();; PacketProtocol pp = new PacketProtocol(this.options); pp.MessageArrived = (data) => { var message = MessageBase.ToMessage(data, data.Length); onMessageReceive?.Invoke(message); }; try { await pp.StartDataRead(stream, token); } catch (Exception xe) { log.LogError(xe.Message); throw; } } }
private async Task ServerReceiveAsync(TcpClient client, CancellationToken token, Action <MessageBase> onMessageReceive) { Action <TcpClient> disposeClient = (c) => { var index = clientList.IndexOf(c); if (index >= 0) { clientList.RemoveAt(index); } if (c.Connected) { c.Close(); } //log.Write($"Client {GetClientDescr(c)} dropped"); }; using (client) { //var buffer = new byte[MessageBase.TransportBufferSize]; var buffer = new byte[options.TransportBufferSize]; var stream = client.GetStream(); //PacketProtocol pp = new PacketProtocol(MessageBase.MaxMessageSize); PacketProtocol pp = new PacketProtocol(options); pp.MessageArrived = (data) => { //Debug.WriteLine($"recd: data of length {data.Length}"); if (data.Length > 0) { var message = MessageBase.ToMessage(data, data.Length); //if(logMessages) //{ // //log.Write($"Received {message.GetType().Name}"); //} message.receivedFrom = client; onMessageReceive?.Invoke(message); } }; try { await pp.StartDataRead(stream, token); //while (!token.IsCancellationRequested) //{ // int count = 0; // count = await stream.ReadAsync(buffer, 0, buffer.Length, token); // if (count > 0) // { // byte[] data = new byte[count]; // Array.Copy(buffer, data, count); // pp.DataReceived(data); // } //} } catch (System.IO.IOException e1) { if (e1.InnerException is SocketException) { var se = (SocketException)e1.InnerException; if (se.SocketErrorCode == SocketError.ConnectionReset) { disposeClient(client); //var index = clientList.IndexOf(client); //if (index >= 0) //{ // clientList.RemoveAt(index); //} } else { //log.Write(LogLevel.Error, $"SocketErrorCode is {se.SocketErrorCode.ToString()}"); } } else { //log.Write(e1.InnerException); } } catch (Exception) { //log.Write(xe); disposeClient(client); } } }