using System.Diagnostics;
|
using System.IO.Ports;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Text;
|
|
namespace LB_VisionProcesses.Communicators.Tcom
|
{
|
public class TCPServer : BaseCommunicator
|
{
|
private TcpListener _tcpListener;
|
private Task _tcpListenerTask;
|
CancellationTokenSource ctsListener = new CancellationTokenSource();
|
private List<TcpClient> _clients = new List<TcpClient>(); // 用于存储所有连接的客户端
|
|
/// <summary>
|
/// 是否多播模式(多播模式会将收到的客户端消息转发给其他客户端)
|
/// </summary>
|
bool isMultiBroadcast = true;
|
|
public TCPServer(string name = "TCP服务器")
|
{
|
CommunicatorConnections.Add("地址", "127.0.0.1");
|
CommunicatorConnections.Add("端口", "1111");
|
CommunicatorBrand = CommunicatorBrand.TCPServer;
|
CommunicatorName = name;
|
}
|
|
public override bool Connect()
|
{
|
try
|
{
|
// 创建一个TCP监听器
|
if (bConnected)
|
Disconnect();
|
|
int PORT = 0;
|
if (!int.TryParse(this.CommunicatorConnections["端口"].ToString(), out PORT))
|
{
|
Msg = string.Format("端口未设置");
|
return false;
|
}
|
if (!CommunicatorConnections.Contains("地址"))
|
{
|
Msg = string.Format("地址未设置");
|
return false;
|
}
|
string IP = CommunicatorConnections["地址"].ToString();
|
|
_tcpListener = new TcpListener(IPAddress.Parse(IP), PORT);
|
_tcpListener.Start();
|
bConnected = true;
|
|
//// 启动心跳线程(服务器不需要心跳线程)
|
//heartbeatThread = new Thread(SendHeartbeat);
|
//heartbeatThread.IsBackground = true;
|
//heartbeatThread.Start();
|
|
// 启动监听线程
|
ctsListener = new CancellationTokenSource();
|
_tcpListenerTask = ListenForClientsAsync(ctsListener.Token);
|
|
return true;
|
}
|
catch (Exception ex)
|
{
|
Msg = $"失败,服务器已经启动: {ex.Message}";
|
return false;
|
}
|
}
|
|
public override bool Disconnect()
|
{
|
try
|
{
|
bConnected = false;
|
|
if (_tcpListenerTask != null)
|
ctsListener.Cancel();
|
|
if (_tcpListener != null)
|
{
|
_tcpListener.Stop();
|
_tcpListener = null;
|
}
|
|
return true;
|
}
|
catch
|
{
|
bConnected = false;
|
Msg = "失败,服务器已经停止";
|
return true;
|
}
|
}
|
|
private async Task ListenForClientsAsync(CancellationToken cancellationToken)
|
{
|
while (bConnected && !cancellationToken.IsCancellationRequested)
|
{
|
try
|
{
|
//// 阻塞等待客户端连接
|
//var tcpClient = _tcpListener.AcceptTcpClient();
|
|
//// 将客户端添加到客户端列表中
|
//lock (_clients)
|
//{
|
// _clients.Add(tcpClient);
|
//}
|
|
//// 启动一个线程来处理客户端消息
|
//var clientThread = new Thread(HandleClientComm);
|
//clientThread.Start(tcpClient);
|
|
// 异步等待客户端连接(可取消)
|
var tcpClient = await _tcpListener.AcceptTcpClientAsync(cancellationToken);
|
|
lock (_clients)
|
{
|
_clients.Add(tcpClient);
|
}
|
|
// 使用 Task.Run 代替 Thread
|
_ = Task.Run(() => HandleClientComm(tcpClient), cancellationToken);
|
}
|
catch { }
|
}
|
}
|
|
private void HandleClientComm(object obj)
|
{
|
if (obj == null || !(obj is TcpClient))
|
return;
|
|
try
|
{
|
var tcpClient = (TcpClient)obj;
|
NetworkStream stream = tcpClient.GetStream();
|
while (bConnected)
|
{
|
byte[] buffer = new byte[1024];
|
int bytesRead = stream.Read(buffer, 0, buffer.Length);
|
|
if (bytesRead == 0)
|
break;
|
|
strReceiveMsg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
|
|
List<TcpClient> listRemoveTcpClients = new List<TcpClient>();
|
foreach (var client in _clients)
|
{
|
if (isMultiBroadcast && client != tcpClient) // 如果是多播模式且不是发送者
|
{
|
try
|
{
|
SendMessageToClient(client, strReceiveMsg);
|
}
|
catch (Exception ex)
|
{
|
Debug.WriteLine($"发送消息到 {client.ToString()} 客户端时发生错误: {ex.Message}");
|
listRemoveTcpClients.Add(client);
|
}
|
}
|
}
|
foreach (var offlineTcpClient in listRemoveTcpClients)
|
{
|
lock (_clients)
|
{
|
_clients.Remove(offlineTcpClient);
|
}
|
}
|
|
try
|
{
|
TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg); // 触发运行事件
|
}
|
catch { }
|
try
|
{
|
MessageReceived?.Invoke(strReceiveMsg); // 触发消息接收事件
|
}
|
catch { }
|
}
|
}
|
catch { }
|
}
|
|
public void SendMessageToClient(TcpClient client, string message)
|
{
|
NetworkStream stream = client.GetStream();
|
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
|
stream.Write(messageBytes, 0, messageBytes.Length);
|
stream.Flush();
|
}
|
|
|
public override bool SendMessage(byte[] sBytes)
|
{
|
return SendMessage(sBytes.ToString());
|
}
|
|
public override bool SendMessage(string message)
|
{
|
//空消息不发送
|
if (string.IsNullOrEmpty(message) || message.Trim() == "")
|
return true;
|
List<TcpClient> listRemoveTcpClients = new List<TcpClient>();
|
foreach (var client in _clients)
|
{
|
try
|
{
|
SendMessageToClient(client, message);
|
}
|
catch (Exception ex)
|
{
|
Debug.WriteLine($"发送消息到 {client.ToString()} 客户端时发生错误: {ex.Message}");
|
listRemoveTcpClients.Add(client);
|
}
|
}
|
|
foreach (var offlineTcpClient in listRemoveTcpClients)
|
{
|
lock (_clients)
|
{
|
_clients.Remove(offlineTcpClient);
|
}
|
}
|
|
return true;
|
}
|
}
|
}
|