226 lines
7.4 KiB
C#
226 lines
7.4 KiB
C#
using Microsoft.Extensions.Hosting;
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace DOAN.ServiceCore.MyHub
|
||
{
|
||
|
||
|
||
/// <summary>
|
||
/// Socket 服务端工具类(你的“接受端”),并作为 IHostedService 运行
|
||
/// 功能:监听端口,与网关(客户端)建立长连接,支持收发字节数据(byte[])
|
||
/// </summary>
|
||
public class SocketGatewayServer : IHostedService, IDisposable
|
||
{
|
||
// 【原有成员变量保持不变】
|
||
private TcpListener _listener;
|
||
private bool _isRunning;
|
||
private Thread _acceptThread;
|
||
|
||
private TcpClient _connectedClient;
|
||
private NetworkStream _clientStream;
|
||
private bool _clientConnected;
|
||
|
||
private readonly string _listenIp;
|
||
private readonly int _listenPort;
|
||
|
||
public SocketGatewayServer(string listenIp = "127.0.0.1", int listenPort = 8888)
|
||
{
|
||
_listenIp = listenIp;
|
||
_listenPort = listenPort;
|
||
}
|
||
|
||
// ======================
|
||
// 实现 IHostedService 接口
|
||
// ======================
|
||
|
||
/// <summary>
|
||
/// 由 ASP.NET Core 在应用启动时调用,用于启动服务
|
||
/// </summary>
|
||
public Task StartAsync(CancellationToken cancellationToken)
|
||
{
|
||
Console.WriteLine("[SocketGatewayServer] 正在启动...");
|
||
|
||
try
|
||
{
|
||
IPAddress ipAddress = string.IsNullOrEmpty(_listenIp) || _listenIp == "0.0.0.0"
|
||
? IPAddress.Any
|
||
: IPAddress.Parse(_listenIp);
|
||
|
||
_listener = new TcpListener(ipAddress, _listenPort);
|
||
_listener.Start();
|
||
_isRunning = true;
|
||
|
||
Console.WriteLine($"✅ Socket 服务端已启动,正在监听 [{_listenIp}]:{_listenPort}");
|
||
|
||
_acceptThread = new Thread(AcceptClient);
|
||
_acceptThread.IsBackground = true;
|
||
_acceptThread.Start();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"❌ 启动服务端失败: {ex.Message}");
|
||
Stop();
|
||
}
|
||
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 由 ASP.NET Core 在应用停止时调用,用于停止服务
|
||
/// </summary>
|
||
public Task StopAsync(CancellationToken cancellationToken)
|
||
{
|
||
Console.WriteLine("[SocketGatewayServer] 正在停止...");
|
||
Stop(); // 内部会调用 DisconnectClient() 和 _listener.Stop()
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 等待并接受一个客户端(网关)连接
|
||
/// </summary>
|
||
private void AcceptClient()
|
||
{
|
||
try
|
||
{
|
||
while (_isRunning)
|
||
{
|
||
Console.WriteLine(" 等待网关(客户端)连接...");
|
||
|
||
TcpClient client = _listener.AcceptTcpClient(); // 阻塞直到客户端连接
|
||
Console.WriteLine($"网关(客户端)已连接: {client.Client.RemoteEndPoint}");
|
||
StartReceiving();
|
||
|
||
lock (this)
|
||
{
|
||
// 断开之前的连接(如果存在)
|
||
_connectedClient?.Close();
|
||
_connectedClient = client;
|
||
_clientStream = client.GetStream();
|
||
_clientConnected = true;
|
||
|
||
Console.WriteLine("已建立长连接,可以开始收发字节数据");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (_isRunning)
|
||
Console.WriteLine($"接受客户端时出错: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 向网关(客户端)发送字节数据(byte[])
|
||
/// </summary>
|
||
/// <param name="data">要发送的字节数据</param>
|
||
/// <returns>是否发送成功</returns>
|
||
public bool SendToGateway(byte[] data)
|
||
{
|
||
if (!_clientConnected || _clientStream == null || _connectedClient == null)
|
||
{
|
||
Console.WriteLine(" 未连接到网关,无法发送数据");
|
||
return false;
|
||
}
|
||
|
||
try
|
||
{
|
||
_clientStream.Write(data, 0, data.Length);
|
||
Console.WriteLine($" 已发送 {data.Length} 字节数据给网关");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"发送数据失败: {ex.Message}");
|
||
DisconnectClient();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// (可选)接收来自网关的字节数据
|
||
/// </summary>
|
||
public void StartReceiving()
|
||
{
|
||
Thread receiveThread = new Thread(ReceiveLoop);
|
||
receiveThread.IsBackground = true;
|
||
receiveThread.Start();
|
||
}
|
||
|
||
private void ReceiveLoop()
|
||
{
|
||
byte[] buffer = new byte[4096]; // 可根据需求调整缓冲区大小
|
||
|
||
try
|
||
{
|
||
while (_clientConnected && _connectedClient != null && _clientStream != null)
|
||
{
|
||
if (_clientStream.DataAvailable)
|
||
{
|
||
int bytesRead = _clientStream.Read(buffer, 0, buffer.Length);
|
||
if (bytesRead > 0)
|
||
{
|
||
byte[] receivedData = new byte[bytesRead];
|
||
Buffer.BlockCopy(buffer, 0, receivedData, 0, bytesRead);
|
||
|
||
Console.WriteLine($"收到来自网关的 {bytesRead} 字节数据");
|
||
|
||
// 🔧 新增:将收到的 byte[] 使用 GBK 编码转换为字符串
|
||
string receivedText = Encoding.GetEncoding("GBK").GetString(receivedData);
|
||
|
||
Console.WriteLine($"GBK 解码后的报文内容: {receivedText}");
|
||
|
||
// TODO: 你可以在这里进一步处理 receivedText 或 receivedData
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Thread.Sleep(100); // 避免空转消耗 CPU
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"接收数据时出错: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
Console.WriteLine("接收线程已退出");
|
||
}
|
||
}
|
||
|
||
private void DisconnectClient()
|
||
{
|
||
lock (this)
|
||
{
|
||
_clientConnected = false;
|
||
_clientStream?.Close();
|
||
_connectedClient?.Close();
|
||
_clientStream = null;
|
||
_connectedClient = null;
|
||
Console.WriteLine("🔌 已断开与网关的连接");
|
||
}
|
||
}
|
||
|
||
|
||
public void Stop()
|
||
{
|
||
_isRunning = false;
|
||
DisconnectClient();
|
||
_listener?.Stop();
|
||
Console.WriteLine("🛑 Socket 服务端已停止");
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
Stop();
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
|
||
// ... [其他原有方法:AcceptClient, SendToGateway, ReceiveLoop, etc.]
|
||
}
|
||
}
|