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 = STcpPacketHeader.HEADER_LENGTH; // private readonly int BUFFER_SIZE = 1024; private readonly string FILE_SAVE_FOLDER = @".\"; 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; while (true) { Thread.Sleep(50); if (_cts.IsCancellationRequested) break; int headerBytesRead = await _stream.ReadAsync(headerBuffer, 0, HEADER_SIZE); if (headerBytesRead != HEADER_SIZE) { WriteError(new Exception("Cannot read header")); return; } STcpPacketHeader header = new STcpPacketHeader(headerBuffer); int dataSize = header.DataLength; dataBuffer = new byte[dataSize]; 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); } else if (header.Type == PacketType.RES_CLIENT_LIST) { STcpClientListResPacket packet = new STcpClientListResPacket(dataBuffer); foreach (var client in packet.Clients) { WriteMessage(client); } } else if (header.Type == PacketType.RES_FILE) { STcpFileResPacket packet = new STcpFileResPacket(dataBuffer, FILE_SAVE_FOLDER); WriteMessage($"File({packet.FileName}) saved."); } } }, _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 async void RequireClientList() { try { STcpClientListReqPacket packet = new STcpClientListReqPacket(); await _stream.WriteAsync(packet.Serialize()); } catch (Exception ex) { WriteError(ex); } } public async void RequireFile(string path) { try { STcpFileReqPacket packet = new STcpFileReqPacket(path); await _stream.WriteAsync(packet.Serialize()); } 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); } } }