2025-11-13 15:31:08 +08:00

226 lines
7.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.]
}
}