Files
FATrace/FATrace.OEMApp/Services/TouchSocketServer_使用示例.md
2026-01-13 15:03:02 +08:00

411 lines
12 KiB
Markdown
Raw 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.
# TouchSocketServer 使用示例
## 概述
`TouchSocketServer` 是一个基于 TouchSocket 4.0 实现的稳定可靠的 Socket 服务器,支持多客户端同时连接。
## 主要特性
- ✅ 基于 TouchSocket 4.0,性能优异
- ✅ 支持多客户端同时连接
- ✅ UTF-8 编码
- ✅ 详细的 NLog 日志记录
- ✅ 事件驱动架构,方便外部处理业务逻辑
- ✅ 支持单播和广播发送数据
- ✅ 异步操作,性能优秀
## 配置参数
```csharp
// 创建服务实例
var socketServer = new TouchSocketServer();
// 配置参数(可选,有默认值)
socketServer.ListenIp = "127.0.0.1"; // 监听 IP默认 127.0.0.1
socketServer.ListenPort = 6001; // 监听端口,默认 6001
socketServer.ReceiveTimeout = 30000; // 接收超时(毫秒),默认 30000
socketServer.SendTimeout = 30000; // 发送超时(毫秒),默认 30000
socketServer.BufferLength = 1024 * 64; // 缓冲区大小,默认 64KB
socketServer.MaxCount = 10000; // 最大连接数,默认 10000
```
## 基本使用
### 1. 启动服务器
```csharp
// 启动服务器(异步)
bool success = await socketServer.StartAsync();
if (success)
{
Console.WriteLine("服务器启动成功");
}
else
{
Console.WriteLine("服务器启动失败");
}
```
### 2. 订阅事件
#### 数据接收事件
```csharp
socketServer.DataReceived += (sender, e) =>
{
// 处理接收到的数据
Console.WriteLine($"收到数据ClientId={e.ClientId}, IP={e.RemoteIp}:{e.RemotePort}");
Console.WriteLine($"数据内容:{e.Data}");
Console.WriteLine($"接收时间:{e.ReceivedTime}");
// 在这里处理你的业务逻辑
// 例如:解析数据、保存到数据库、触发其他操作等
};
```
#### 客户端连接事件
```csharp
socketServer.ClientConnected += (sender, e) =>
{
Console.WriteLine($"客户端已连接ClientId={e.ClientId}, IP={e.RemoteIp}:{e.RemotePort}");
Console.WriteLine($"连接时间:{e.ConnectedTime}");
Console.WriteLine($"当前连接数:{socketServer.ConnectedClientCount}");
};
```
#### 客户端断开事件
```csharp
socketServer.ClientDisconnected += (sender, e) =>
{
Console.WriteLine($"客户端已断开ClientId={e.ClientId}, IP={e.RemoteIp}:{e.RemotePort}");
Console.WriteLine($"断开原因:{e.Reason}");
Console.WriteLine($"断开时间:{e.DisconnectedTime}");
Console.WriteLine($"当前连接数:{socketServer.ConnectedClientCount}");
};
```
#### 服务器错误事件
```csharp
socketServer.ServerError += (sender, ex) =>
{
Console.WriteLine($"服务器发生错误:{ex.Message}");
Console.WriteLine($"错误堆栈:{ex.StackTrace}");
};
```
### 3. 发送数据
#### 向指定客户端发送数据
```csharp
string clientId = "Session_1_xxx"; // 从事件参数中获取的 ClientId
string data = "Hello Client!";
bool success = socketServer.SendToClient(clientId, data);
if (success)
{
Console.WriteLine("数据发送成功");
}
```
#### 向所有客户端广播数据
```csharp
string data = "Broadcast Message to All!";
int successCount = socketServer.Broadcast(data);
Console.WriteLine($"广播成功发送到 {successCount} 个客户端");
```
### 4. 断开指定客户端
```csharp
string clientId = "Session_1_xxx";
bool success = socketServer.DisconnectClient(clientId);
if (success)
{
Console.WriteLine("客户端已断开");
}
```
### 5. 获取所有已连接客户端
```csharp
List<string> clientIds = socketServer.GetConnectedClientIds();
Console.WriteLine($"当前连接的客户端数量:{clientIds.Count}");
foreach (var clientId in clientIds)
{
Console.WriteLine($" - {clientId}");
}
```
### 6. 获取客户端信息
```csharp
string clientId = "Session_1_xxx";
string info = socketServer.GetClientInfo(clientId);
Console.WriteLine($"客户端信息:{info}");
```
### 7. 停止服务器
```csharp
await socketServer.StopAsync();
Console.WriteLine("服务器已停止");
```
## 完整示例
```csharp
using FATrace.OEMApp.Services;
using System;
using System.Threading.Tasks;
public class TouchSocketServerExample
{
private TouchSocketServer _socketServer;
public async Task RunAsync()
{
// 1. 创建服务实例
_socketServer = new TouchSocketServer
{
ListenIp = "0.0.0.0", // 监听所有网卡
ListenPort = 6001,
ReceiveTimeout = 30000,
SendTimeout = 30000
};
// 2. 订阅事件
_socketServer.DataReceived += OnDataReceived;
_socketServer.ClientConnected += OnClientConnected;
_socketServer.ClientDisconnected += OnClientDisconnected;
_socketServer.ServerError += OnServerError;
// 3. 启动服务器
bool success = await _socketServer.StartAsync();
if (!success)
{
Console.WriteLine("服务器启动失败");
return;
}
Console.WriteLine("服务器已启动,按任意键停止...");
Console.ReadKey();
// 4. 停止服务器
await _socketServer.StopAsync();
}
private void OnDataReceived(object sender, TouchSocketServer.DataReceivedEventArgs e)
{
Console.WriteLine($"[数据接收] ClientId={e.ClientId}, 数据={e.Data}");
// 处理业务逻辑
// 例如:回复客户端
_socketServer.SendToClient(e.ClientId, $"收到:{e.Data}");
}
private void OnClientConnected(object sender, TouchSocketServer.ClientConnectedEventArgs e)
{
Console.WriteLine($"[客户端连接] ClientId={e.ClientId}, IP={e.RemoteIp}:{e.RemotePort}");
// 欢迎消息
_socketServer.SendToClient(e.ClientId, "欢迎连接到服务器!");
}
private void OnClientDisconnected(object sender, TouchSocketServer.ClientDisconnectedEventArgs e)
{
Console.WriteLine($"[客户端断开] ClientId={e.ClientId}, 原因={e.Reason}");
}
private void OnServerError(object sender, Exception ex)
{
Console.WriteLine($"[服务器错误] {ex.Message}");
}
}
```
## 在 WinForms 中使用
```csharp
public partial class MainApp : Form
{
private TouchSocketServer _socketServer;
private async void MainApp_Load(object sender, EventArgs e)
{
// 初始化 Socket 服务
_socketServer = new TouchSocketServer
{
ListenIp = "127.0.0.1",
ListenPort = 6001
};
// 订阅事件(注意:需要使用 Invoke 更新 UI
_socketServer.DataReceived += (s, args) =>
{
this.Invoke(new Action(() =>
{
// 更新 UI
txtLog.AppendText($"收到数据:{args.Data}\r\n");
}));
};
// 启动服务器
bool success = await _socketServer.StartAsync();
if (success)
{
lblStatus.Text = "服务器运行中";
lblStatus.ForeColor = Color.Green;
}
}
private async void MainApp_FormClosing(object sender, FormClosingEventArgs e)
{
// 停止服务器
if (_socketServer != null && _socketServer.IsRunning)
{
await _socketServer.StopAsync();
}
}
private void btnSendToAll_Click(object sender, EventArgs e)
{
// 广播消息
string message = txtMessage.Text;
int count = _socketServer.Broadcast(message);
MessageBox.Show($"已发送到 {count} 个客户端");
}
}
```
## 协议说明
### 数据格式
- **编码**UTF-8
- **数据传输**原始字节流TouchSocket 会自动处理)
- **每次接收**:通过事件参数获取完整数据
### 客户端示例C#
```csharp
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
public class SimpleClient
{
public static async Task Main()
{
using var client = new TcpClient();
await client.ConnectAsync("127.0.0.1", 6001);
var stream = client.GetStream();
var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true };
var reader = new StreamReader(stream, Encoding.UTF8);
// 发送数据
await writer.WriteAsync("Hello Server!");
await writer.FlushAsync();
// 接收数据
char[] buffer = new char[1024];
int count = await reader.ReadAsync(buffer, 0, buffer.Length);
string response = new string(buffer, 0, count);
Console.WriteLine($"服务器回复:{response}");
}
}
```
### 客户端示例Python
```python
import socket
# 连接服务器
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 6001))
# 发送数据
message = "Hello Server!"
client.send(message.encode('utf-8'))
# 接收数据
response = client.recv(1024).decode('utf-8')
print(f"服务器回复:{response}")
client.close()
```
## 日志说明
TouchSocketServer 使用 NLog 记录详细日志,包括:
- **Info 级别**:服务器启动/停止、客户端连接/断开、广播完成
- **Debug 级别**:数据接收/发送的详细内容、客户端正在连接
- **Warn 级别**:参数错误、客户端未找到、服务器未运行
- **Error 级别**:异常堆栈信息
日志示例:
```
2026-01-01 22:00:00.123 [INFO] 正在启动 Socket 服务器监听地址127.0.0.1:6001超时时间30000毫秒
2026-01-01 22:00:00.456 [INFO] Socket 服务器启动成功监听地址127.0.0.1:6001
2026-01-01 22:00:05.789 [INFO] 客户端已连接ClientId=xxx远程地址=127.0.0.1:54321当前连接数=1
2026-01-01 22:00:10.123 [DEBUG] 接收到客户端数据ClientId=xxx远程地址=127.0.0.1:54321数据长度=13字符内容=Hello Server!
```
## 注意事项
1. **线程安全**:所有公共方法都是线程安全的,可以在多线程环境中使用
2. **事件处理**:事件回调在后台线程执行,如需更新 UI请使用 `Invoke`
3. **超时设置**:如果客户端长时间无数据交互,会自动断开连接
4. **异步方法**StartAsync 和 StopAsync 是异步方法,需要使用 await
5. **异常处理**:所有异常都会被捕获并记录日志,不会导致服务器崩溃
6. **动态类型**:内部使用 dynamic 类型管理客户端,兼容 TouchSocket 4.0
## 常见问题
### Q1: 如何监听所有网卡?
```csharp
socketServer.ListenIp = "0.0.0.0";
```
### Q2: 如何获取客户端的 ClientId
ClientId 会在事件参数中提供(`DataReceivedEventArgs.ClientId`),你可以保存它用于后续发送数据。
### Q3: 如何实现心跳检测?
可以在客户端定期发送心跳数据,服务器通过 `ReceiveTimeout` 自动断开无响应的客户端。
### Q4: 为什么编译有警告?
这些是 C# 8.0 的可空引用类型警告,不影响功能,可以忽略。
### Q5: TouchSocket 4.0 与文档不一致?
是的TouchSocket 4.0.5 的 API 与官方文档有所不同,本实现已经适配了实际的 API。
## 性能建议
1. **连接数**:默认支持 10000 个并发连接,可根据需要调整 `MaxCount`
2. **缓冲区**:默认 64KB 缓冲区,适合大多数场景
3. **超时时间**:根据实际网络环境调整超时时间
4. **日志级别**:生产环境建议将 Debug 日志关闭,减少性能开销
## 与 SocketService 对比
| 特性 | TouchSocketServer | SocketService (原生) |
|------|-------------------|---------------------|
| 基础框架 | TouchSocket 4.0 | 原生 TcpListener |
| 性能 | ⭐⭐⭐⭐⭐ 更优秀 | ⭐⭐⭐⭐ 优秀 |
| 稳定性 | ⭐⭐⭐⭐⭐ 非常稳定 | ⭐⭐⭐⭐⭐ 非常稳定 |
| 依赖 | TouchSocket 包 | 仅 .NET 原生库 |
| 复杂度 | 简单 | 中等 |
| 推荐度 | ✅ **强烈推荐** | ✅ 推荐 |
两个实现都非常优秀TouchSocketServer 基于成熟的 TouchSocket 框架性能更优SocketService 基于原生库,无额外依赖。根据你的需求选择即可!