You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.3 KiB

2 years ago
using STcpHelper.Packet;
using System;
using System.Collections.Generic;
2 years ago
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<string> MessageCallback;
public event EventHandler<Exception> 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 = @".\";
2 years ago
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 () =>
{
2 years ago
byte[] headerBuffer = new byte[HEADER_SIZE];
byte[] dataBuffer;
while (true)
{
Thread.Sleep(50);
if (_cts.IsCancellationRequested)
break;
2 years ago
int headerBytesRead = await _stream.ReadAsync(headerBuffer, 0, HEADER_SIZE);
if (headerBytesRead != HEADER_SIZE)
2 years ago
{
WriteError(new Exception("Cannot read header"));
return;
}
STcpPacketHeader header = new STcpPacketHeader(headerBuffer);
int dataSize = header.DataLength;
dataBuffer = new byte[dataSize];
2 years ago
int totalRecv = 0;
while (totalRecv < dataSize)
{
int dataBytesRead = await _stream.ReadAsync(dataBuffer, totalRecv, dataSize - totalRecv);
2 years ago
totalRecv += dataBytesRead;
}
2 years ago
if (header.Type == PacketType.TEXT)
{
STcpTextPacket packet = new STcpTextPacket(dataBuffer);
WriteMessage(packet.Text);
}
2 years ago
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);
}
}
2 years ago
private byte[] MakeTextPacket(string text)
{
STcpTextPacket packet = new STcpTextPacket(text);
return packet.Serialize();
}
public async void SendMessage(string message)
{
try
{
2 years ago
byte[] sendBytes = MakeTextPacket(message);
await _stream.WriteAsync(sendBytes);
}
catch (Exception ex)
{
WriteError(ex);
}
}
2 years ago
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);
}
}
}