using STcpHelper.Packet; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace STcpHelper { public class STcpClient { private CancellationTokenSource _cts = new CancellationTokenSource(); public event EventHandler MessageCallback; public event EventHandler ErrorCallback; private TcpClient _client; private NetworkStream _stream; private readonly int HEADER_SIZE = 4; private readonly int BUFFER_SIZE = 1024; public async void Connect(string ip, int port) { try { _client = new TcpClient(); await _client.ConnectAsync(ip, port); _stream = _client.GetStream(); _cts = new CancellationTokenSource(); _ = Task.Run(async () => { byte[] headerBuffer = new byte[HEADER_SIZE]; byte[] dataBuffer = new byte[BUFFER_SIZE]; while (true) { Thread.Sleep(50); if (_cts.IsCancellationRequested) break; int headerBytesRead = await _stream.ReadAsync(headerBuffer, 0, HEADER_SIZE); if (headerBytesRead != 4) { WriteError(new Exception("Cannot read header")); return; } STcpPacketHeader header = new STcpPacketHeader(headerBuffer); short dataSize = header.DataLength; int totalRecv = 0; while (totalRecv < dataSize) { int dataBytesRead = await _stream.ReadAsync(dataBuffer, totalRecv, dataSize - totalRecv); totalRecv += dataBytesRead; } if (header.Type == PacketType.TEXT) { STcpTextPacket packet = new STcpTextPacket(dataBuffer); WriteMessage(packet.Text); } } }, _cts.Token); } catch (Exception ex) { WriteError(ex); } } private byte[] MakeTextPacket(string text) { STcpTextPacket packet = new STcpTextPacket(text); return packet.Serialize(); } public async void SendMessage(string message) { try { byte[] sendBytes = MakeTextPacket(message); await _stream.WriteAsync(sendBytes); } catch (Exception ex) { WriteError(ex); } } public void Close() { try { if (_client == null) return; if (_stream != null) { _stream.Flush(); _stream.Close(); } _cts.Cancel(); _client.Close(); _client.Dispose(); } catch (Exception ex) { WriteError(ex); } } private void WriteMessage(string message) { if (this.MessageCallback != null) this.MessageCallback(this, message); } private void WriteError(Exception ex) { if (this.ErrorCallback != null) this.ErrorCallback(this, ex); } } }