|
|
|
|
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<string> MessageCallback;
|
|
|
|
|
public event EventHandler<Exception> 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|