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.

123 lines
3.7 KiB

using System.Net;
using System.Net.Sockets;
using System.Text;
namespace STcpHelper
{
public class STcpServer
{
private CancellationTokenSource _cts;
private List<TcpClient> _clients;
private readonly int BUFFER_SIZE;
private int _port;
private TcpListener _listener;
public event EventHandler<string> MessageCallback;
public event EventHandler<Exception> ErrorCallback;
public STcpServer(int port, int bufferSize = 1024)
{
_port = port;
BUFFER_SIZE = bufferSize;
_clients = new List<TcpClient>();
}
public async void Start()
{
_listener = new TcpListener(IPAddress.Parse("127.0.0.1"), _port);
_listener.Start();
WriteMessage("Server start...");
_cts = new CancellationTokenSource();
while (true)
{
if (_cts.IsCancellationRequested)
break;
TcpClient client = await _listener.AcceptTcpClientAsync();
_clients.Add(client);
WriteMessage($"Client accepted({client.Client.RemoteEndPoint.ToString()})");
_cts = new CancellationTokenSource();
_ = Task.Run(async () =>
{
using (NetworkStream stream = client.GetStream())
{
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
try
{
while ((bytesRead = await stream.ReadAsync(buffer, 0, BUFFER_SIZE)) > 0)
{
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
WriteMessage($"[{client.Client.RemoteEndPoint.ToString()}] {message}");
// Broadcast
BroadcastMessage(message, client);
if (!IsClientConnected(client))
break;
}
}
catch (Exception ex)
{
WriteError(ex);
}
WriteMessage($"Client disconnected({client.Client.RemoteEndPoint.ToString()})");
client.Close();
_clients.Remove(client);
}
}, _cts.Token);
}
}
public void Stop()
{
_cts.Cancel();
}
private void BroadcastMessage(string message, TcpClient sender)
{
byte[] resonseByte = Encoding.UTF8.GetBytes(message);
foreach (TcpClient client in _clients)
{
if (client != sender && IsClientConnected(client))
client.GetStream().WriteAsync(resonseByte, 0, resonseByte.Length);
}
}
private bool IsClientConnected(TcpClient client)
{
try
{
if (client != null &&
client.Client != null &&
client.Client.Connected)
return true;
}
catch (Exception ex)
{
WriteError(ex);
}
return false;
}
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);
}
}
}