解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# 网络编解ç 器Handlers
> âš ï¸ **æ—§æ ˆæ–‡æ¡£ï¼ˆv12 已退役)**:`NewLife.Net.Handlers` 命å空间与全部 6 个 Handler ç¼–è§£ç 器(`StandardCodec` ç‰ï¼‰å·²æ•´åˆ 。现行å议编解ç 器(`SrmpCodec`/`LengthFieldCodec`/`SplitDataCodec`/`WebSocketCodec`)与å¯ç”¨æ–¹å¼ï¼ˆ`Protocol` 属性)è§ã€Šæ¶ˆæ¯åè®®æ ˆã€‹ã€‚
## 概述
`NewLife.Net.Handlers` 命å空间æä¾›ä¸€å¥—å¯å åŠ çš„ç½‘ç»œç¼–è§£ç 器,用于解决 TCP é•¿è¿žæŽ¥çš„ç²˜åŒ…æ‹†åŒ…ã€æ¶ˆæ¯åºåˆ—化ã€è¯·æ±‚-å“应匹é…ç‰é—®é¢˜ã€‚ç¼–è§£ç 器以处ç†å™¨ï¼ˆ`Handler`ï¼‰å½¢å¼æ³¨å†Œåˆ°ç®¡é“(`Pipeline`),收包时æ£å‘è§£ç ,å‘包时逆å‘ç¼–ç ,支æŒä»»æ„组åˆå åŠ ã€‚
**命å空间**:`NewLife.Net.Handlers`
**文档地å€**:/core/net_handlers
## æ ¸å¿ƒç±»åž‹
| 类型 | 说明 |
|------|------|
| `StandardCodec` | æ ‡å‡†å°åŒ…ç¼–è§£ç ,使用 `DefaultMessage` åŒ…æ ¼å¼ï¼ˆ4 å—节头),集æˆåºåˆ—å·ä¸Žç²˜åŒ…å¤„ç† |
| `LengthFieldCodec` | æŒ‰é•¿åº¦å—æ®µæ‹†åŒ…,支æŒåç§»ã€å¤§å°ç«¯ï¼Œé€‚é… MQTT/LwM2M ç‰å¤šç§åè®® |
| `MessageCodec<T>` | 请求-å“应匹é…é˜Ÿåˆ—ï¼Œæ”¯æŒ `SendMessageAsync` 异æ¥ç‰å¾…å“应 |
| `JsonCodec` | JSON 文本消æ¯ç¼–è§£ç |
| `SplitDataCodec` | 分隔符拆包(默认 `\r\n`) |
| `WebSocketCodec` | WebSocket 帧编解ç |
## 快速开始
### 使用 StandardCodec(最常用)
```csharp
using NewLife.Net;
using NewLife.Net.Handlers;
var server = new NetServer { Port = 12345 };
server.NewSession += (sender, e) =>
{
// æ¯æ¡è¿žæŽ¥æ³¨å†Œç¼–è§£ç 器(顺åºä¸èƒ½é¢ 倒)
var pipeline = e.Session.Pipeline;
pipeline.Add(new StandardCodec());
};
// 收到解ç åŽçš„æ¶ˆæ¯
server.Received += (sender, e) =>
{
if (e.Message is DefaultMessage msg)
{
var text = msg.Payload?.ToStr();
Console.WriteLine($"收到消æ¯: {text}");
}
};
server.Start();
```
### 使用 LengthFieldCodec
```csharp
// 2å—节å°ç«¯é•¿åº¦å—段
pipeline.Add(new LengthFieldCodec { Size = 2 });
// 2å—èŠ‚å¤§ç«¯é•¿åº¦å—æ®µï¼ˆMQTT ç‰å议)
pipeline.Add(new LengthFieldCodec { Size = -2 });
// 头部有2å—节åè®®æ ‡è¯†ï¼Œç„¶åŽæ˜¯2å—èŠ‚é•¿åº¦å—æ®µ
pipeline.Add(new LengthFieldCodec { Offset = 2, Size = 2 });
```
### 异æ¥è¯·æ±‚-å“应
```csharp
// 客户端
var client = new NetUri("tcp://127.0.0.1:12345").CreateRemote();
client.Pipeline.Add(new StandardCodec());
client.Open();
// å‘é€è¯·æ±‚å¹¶ç‰å¾…å“应(最多30秒)
var req = new DefaultMessage { Payload = "ping".GetBytes() };
var resp = await client.SendMessageAsync(req);
if (resp is DefaultMessage reply)
Console.WriteLine($"收到å“应: {reply.Payload?.ToStr()}");
```
## API å‚考
### StandardCodec
继承自 `MessageCodec<IMessage>`,使用 `DefaultMessage`(SRMP å议)å°åŒ…。
```csharp
public class StandardCodec : MessageCodec<IMessage>
{
// æ— é¢å¤–公开属性,通过 MessageCodec<T> 基类é…ç½®
}
```
**DefaultMessage æ ¼å¼**:
```
[1å—节Flag][1å—节Sequence][2å—节长度][Nå—节Payload]
```
- `Flag`:数æ®ç±»åž‹æ ‡å¿—(`DataKinds`),如 `Packet`=0ã€`String`=1
- `Sequence`:自动递增åºåˆ—å·ï¼Œç”¨äºŽè¯·æ±‚-å“应匹é…
- é•¿åº¦å—æ®µåŒ…å« Payload 长度(å°ç«¯ 2 å—节)
### LengthFieldCodec
```csharp
public class LengthFieldCodec : MessageCodec<IPacket>
{
/// <summary>头部åç§»å—èŠ‚æ•°ã€‚é•¿åº¦å—æ®µå‰çš„固定头部大å°ï¼Œé»˜è®¤ 0</summary>
public Int32 Offset { get; set; }
/// <summary>é•¿åº¦å—æ®µå—节数。æ£å€¼=å°ç«¯ï¼Œè´Ÿå€¼=大端,0=å˜é•¿åŽ‹ç¼©ç¼–ç ,默认 2</summary>
/// <remarks>
/// 1/-1 : 1å—节(最大255)
/// 2/-2 : 2å—节(最大65535)
/// 4/-4 : 4å—节(最大4GB)
/// 0 : å˜é•¿åŽ‹ç¼©ç¼–ç (类似 protobuf varint)
/// </remarks>
public Int32 Size { get; set; } = 2;
/// <summary>缓å˜è¿‡æœŸæ—¶é—´ï¼ˆæ¯«ç§’)。ä¸å®Œæ•´åŒ…è¶…æ—¶åŽä¸¢å¼ƒï¼Œé»˜è®¤ 5_000</summary>
public Int32 Expire { get; set; } = 5_000;
}
```
### MessageCodec\<T\>(基类)
```csharp
public class MessageCodec<T> : Handler
{
/// <summary>请求-å“应匹é…队列</summary>
public IMatchQueue? Queue { get; set; }
/// <summary>匹é…队列大å°ï¼Œé»˜è®¤ 256</summary>
public Int32 QueueSize { get; set; } = 256;
/// <summary>ç‰å¾…å“应超时(毫秒),默认 30_000</summary>
public Int32 Timeout { get; set; } = 30_000;
/// <summary>æœ€å¤§ç¼“å˜æ•°æ®ï¼ˆå—节),默认 10MB</summary>
public Int32 MaxCache { get; set; } = 10 * 1024 * 1024;
/// <summary>用户数æ®åŒ…。true=è¯»å–æ—¶è‡ªåŠ¨è§£åŒ… Payload 返回,默认 true</summary>
public Boolean UserPacket { get; set; } = true;
}
```
### SplitDataCodec
适用于文本å议(如 HTTP 头ã€è‡ªå®šä¹‰å‘½ä»¤è¡Œå议):
```csharp
public class SplitDataCodec : Handler
{
/// <summary>粘包分割å—节数æ®ï¼Œé»˜è®¤ 0x0D 0x0A(\r\n)</summary>
public Byte[] SplitData { get; set; }
}
```
## å…¸åž‹å¤„ç†æµç¨‹
**收包**(æ£å‘ `Read`):
```
Socket收到å—节æµ
LengthFieldCodec.Read (拆出完整包,去掉长度头)
StandardCodec.Read ï¼ˆè§£æž DefaultMessageï¼Œå– Payload)
业务层 Received 事件(e.Message 为解ç åŽçš„æ¶ˆæ¯ï¼‰
```
**å‘包**ï¼ˆé€†å‘ `Write`):
```
业务层 session.Send(message)
StandardCodec.Write (å°è£…为 DefaultMessageï¼Œæ·»åŠ åºåˆ—å·ï¼‰
LengthFieldCodec.Write ï¼ˆåœ¨å¤´éƒ¨å†™å…¥é•¿åº¦å—æ®µï¼‰
Socket å‘é€å—节æµ
```
## 使用场景
### 场景一:自定义 JSON åè®®
```csharp
// 使用 LengthFieldCodec 拆包 + JsonCodec åºåˆ—化
pipeline.Add(new LengthFieldCodec { Size = 4 }); // 4å—èŠ‚é•¿åº¦å—æ®µ
pipeline.Add(new JsonCodec());
// å‘é€
session.SendMessage(new { cmd = "login", user = "alice" });
// 接收(e.Message 为已解ç 的对象)
server.Received += (sender, e) =>
{
dynamic msg = e.Message;
Console.WriteLine(msg?.cmd);
};
```
### 场景二:行å议(Telnet é£Žæ ¼ï¼‰
```csharp
pipeline.Add(new SplitDataCodec());
// å‘é€
session.Send("HELLO\r\n");
// 接收(e.Message 为å•行数æ®ï¼ˆå«åˆ†éš”ç¬¦æœ¬èº«ï¼‰ï¼ŒåŒæ¥é“¾è·¯å†…有效;跨轮带出请 Sliceï¼›e.Packet 为整轮原始数æ®ï¼‰
server.Received += (sender, e) =>
{
var line = (e.Message as IPacket)?.ToStr()?.Trim();
// 处ç†å‘½ä»¤è¡Œ
};
```
### 场景三:RPC 异æ¥è°ƒç”¨
```csharp
// 客户端注册 StandardCodec
var client = new NetUri("tcp://127.0.0.1:8080").CreateRemote();
client.Pipeline.Add(new StandardCodec());
client.Open();
// å‘é€è¯·æ±‚ç‰å¾…å“应(如超时抛出 TimeoutException)
var req = new DefaultMessage { Payload = JsonHelper.ToJson(query).GetBytes() };
var resp = await client.SendMessageAsync(req);
// æœåŠ¡ç«¯å›žå¤
// session.ReplyMessage(e, new DefaultMessage { Payload = result.GetBytes() });
```
## 注æ„事项
- **ç¼–è§£ç 器按连接隔离**ï¼šæ¯æ¡è¿žæŽ¥æ–°å»ºå®žä¾‹ï¼Œä¸å¯è·¨è¿žæŽ¥å…±äº«ï¼ˆå°¤å…¶æ˜¯å¸¦ç¼“å˜çš„æ‹†åŒ…器)。
- **拆包器在å‰**:`LengthFieldCodec` 必须在 `StandardCodec` 之剿³¨å†Œï¼›å¦åˆ™æ”¶åˆ°çš„æ˜¯ç²˜åŒ…æ•°æ®ã€‚
- **è¿žæŽ¥å…³é—æ—¶æ¸…ç†ç¼“å˜**:`PacketCodec` 内部有å—节缓å˜ï¼Œæ–开连接时自动清ç†ï¼Œä¸å…³é—è¿žæŽ¥ä¸æ¸…ç†ï¼Œé•¿æ—¶é—´ä¸æ´»è·ƒä¼šå¯¼è‡´å†…å˜æ»žç•™ã€‚
- **`MaxCache` 防内å˜çˆ†ç‚¸**ï¼šè¶…å¤§æˆ–ç•¸å½¢åŒ…ä¼šå¯¼è‡´ç¼“å˜æŒç»å¢žé•¿ï¼ŒåŠ¡å¿…æ ¹æ®å议最大包大å°åˆç†è®¾ç½® `MaxCache`。
- **`Timeout` 按业务调整**:默认 30 秒适åˆå¤§å¤šæ•° RPCï¼Œå¯¹äºŽæ–‡ä»¶ä¼ è¾“ç‰é•¿è€—æ—¶æ“作应适当增大。
|