解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# ç®¡é“æ¨¡åž‹Pipeline
> âš ï¸ **æ—§æ ˆæ–‡æ¡£ï¼ˆv12 已退役)**:`IPipeline`/`Pipeline`/`Handler`/`IHandlerContext` 全家æ—å·²æ•´åˆ ã€‚çŽ°è¡Œæ•°æ®æµï¼šå议模å¼ç» `MessagePump` + `Received` äº‹ä»¶ï¼›éœ€è¦æ—è·¯å¤„ç†æ—¶ä½¿ç”¨ä¼šè¯ `INetHandler`(è§ã€Šæ¶ˆæ¯åè®®æ ˆã€‹Â§5.2)。
## 概述
`IPipeline`/`Pipeline` 是 NewLife.Core 网络与消æ¯å¤„ç†çš„æ ¸å¿ƒæ‰©å±•机制,基于责任链模å¼å°†ç¼–è§£ç ã€åŽ‹ç¼©ã€åР坆ç‰é€»è¾‘拆分为独立的处ç†å™¨èŠ‚ç‚¹ï¼Œé€šè¿‡åŒå‘链表串è”ã€‚æ¯æ¡è¿žæŽ¥å¯¹åº”独立的管é“实例,收包(`Read`)沿头部到尾部æ£å‘ä¼ é€’ï¼Œå‘包(`Write`)沿尾部到头部逆å‘ä¼ é€’ã€‚
**命å空间**:`NewLife.Model`
**文档地å€**:/core/pipeline
## æ ¸å¿ƒç‰¹æ€§
- **åŒå‘链路**:åŒä¸€ç®¡é“åŒæ—¶æ”¯æŒè§£ç (`Read`)和编ç (`Write`)两个方å‘
- **链å¼ä¼ 递**:å‰ä¸€ä¸ªå¤„ç†å™¨çš„输出自动æˆä¸ºä¸‹ä¸€ä¸ªçš„输入
- **生命周期事件**:`Open`(æ£å‘)/ `Close`(逆å‘)/ `Error`(æ£å‘)与网络会è¯åŒæ¥
- **线程安全**:`Add`/`Remove`/`Clear` å†…éƒ¨åŠ é”,链表修改安全
- **å¯ç»„åˆ**:按需å åŠ æ‹†åŒ…ã€è§£å¯†ã€åºåˆ—化ç‰å¤„ç†å™¨ï¼Œæ— éœ€ä¿®æ”¹æ ¸å¿ƒé€»è¾‘
## æ•°æ®æµæ–¹å‘
```
收包(Read,æ£å‘ Head → Tail):
Socket → Handler[0].Read → Handler[1].Read → ... → Handler[n].FireRead → 业务层
å‘包(Writeï¼Œé€†å‘ Tail → Head):
业务层 → Handler[n].Write → ... → Handler[1].Write → Handler[0].FireWrite → Socket
Open/Error(æ£å‘) Close(逆å‘)
```
## 快速开始
```csharp
using NewLife.Model;
using NewLife.Net.Handlers;
// 1. 创建管é“并注册处ç†å™¨ï¼ˆé¡ºåºå³æ£å‘处ç†é¡ºåºï¼‰
var pipeline = new Pipeline();
pipeline.Add(new LengthFieldCodec { Size = 2 }); // 粘包拆包
pipeline.Add(new StandardCodec()); // 消æ¯ç¼–è§£ç
// 2. 创建上下文(通常由 NetServer/NetClient 自动完æˆï¼‰
var ctx = pipeline.CreateContext(session);
// 3. 收包:将原始 IPacket ä¼ å…¥ç®¡é“,返回业务消æ¯
var msg = pipeline.Read(ctx, receivedPacket);
// 4. å‘包:将业务消æ¯ä¼ 入管é“,返回编ç åŽçš„ IPacket
var pk = pipeline.Write(ctx, myMessage) as IPacket;
session.Send(pk);
```
## API å‚考
### IPipeline 接å£
#### 管ç†å¤„ç†å™¨
```csharp
/// <summary>æ·»åŠ å¤„ç†å™¨åˆ°æœ«å°¾</summary>
void Add(IPipelineHandler handler);
/// <summary>移除处ç†å™¨</summary>
Boolean Remove(IPipelineHandler handler);
/// <summary>清空所有处ç†å™¨</summary>
void Clear();
```
#### 执行æ“作
```csharp
/// <summary>读å–(收包),æ£å‘ Head→Tailã€‚å¤šæ¶ˆæ¯æ—¶è¿”回 null 并多次回调 FireRead</summary>
Object? Read(IHandlerContext context, Object message);
/// <summary>写入(å‘åŒ…ï¼‰ï¼Œé€†å‘ Tail→Head</summary>
Object? Write(IHandlerContext context, Object message);
/// <summary>打开连接,æ£å‘ä¼ æ’</summary>
Boolean Open(IHandlerContext context);
/// <summary>å…³é—连接,逆å‘ä¼ æ’</summary>
Boolean Close(IHandlerContext context, String reason);
/// <summary>å‘生错误,æ£å‘ä¼ æ’</summary>
Boolean Error(IHandlerContext context, Exception exception);
```
### Pipeline 类属性
```csharp
public class Pipeline : IPipeline
{
/// <summary>处ç†å™¨é›†åˆï¼ˆé¡ºåºï¼‰</summary>
public IList<IPipelineHandler> Handlers { get; }
/// <summary>头部处ç†å™¨ï¼ˆæ£å‘起点)</summary>
public IPipelineHandler? Head { get; }
/// <summary>尾部处ç†å™¨ï¼ˆé€†å‘起点)</summary>
public IPipelineHandler? Tail { get; }
}
```
### IPipelineHandler / Handler
```csharp
public interface IPipelineHandler
{
/// <summary>å‰é©±èŠ‚ç‚¹ï¼ˆé€†å‘下一跳)</summary>
IPipelineHandler? Prev { get; set; }
/// <summary>åŽç»§èŠ‚ç‚¹ï¼ˆæ£å‘下一跳)</summary>
IPipelineHandler? Next { get; set; }
Object? Read(IHandlerContext context, Object message);
Object? Write(IHandlerContext context, Object message);
Boolean Open(IHandlerContext context);
Boolean Close(IHandlerContext context, String reason);
Boolean Error(IHandlerContext context, Exception exception);
}
```
`Handler` 是 `IPipelineHandler` 的抽象基类,默认实现是将消æ¯ä¼ 递给链表ä¸çš„下一个节点,业务实现åªéœ€è¦†å†™å…³å¿ƒçš„æ–¹æ³•。
## 自定义处ç†å™¨
### ç¤ºä¾‹ï¼šè®°å½•æ”¶å‘æ—¥å¿—
```csharp
public class LogHandler : Handler
{
public override Object? Read(IHandlerContext context, Object message)
{
XTrace.WriteLine("收到: {0}", message);
return base.Read(context, message); // å¿…é¡»ä¼ é€’ç»™ä¸‹ä¸€èŠ‚ç‚¹
}
public override Object? Write(IHandlerContext context, Object message)
{
XTrace.WriteLine("å‘é€: {0}", message);
return base.Write(context, message);
}
}
// 注册到管é“
pipeline.Add(new LogHandler());
```
### ç¤ºä¾‹ï¼šåŠ å¯†/解密处ç†å™¨
```csharp
public class EncryptHandler : Handler
{
private readonly Byte[] _key;
public EncryptHandler(Byte[] key) => _key = key;
public override Object? Read(IHandlerContext context, Object message)
{
if (message is IPacket pk)
{
var decrypted = Decrypt(pk.GetSpan(), _key);
return base.Read(context, new ArrayPacket(decrypted));
}
return base.Read(context, message);
}
public override Object? Write(IHandlerContext context, Object message)
{
if (message is IPacket pk)
{
var encrypted = Encrypt(pk.GetSpan(), _key);
return base.Write(context, new ArrayPacket(encrypted));
}
return base.Write(context, message);
}
}
```
## 与 NetServer/NetClient 集æˆ
NetServer å’Œ NetClient è‡ªåŠ¨ä¸ºæ¯æ¡è¿žæŽ¥åˆ›å»ºç®¡é“,å¯åœ¨ `NewSession` äº‹ä»¶ä¸æ³¨å†Œç¼–è§£ç 器:
```csharp
var server = new NetServer { Port = 12345 };
server.NewSession += (sender, e) =>
{
var pipeline = e.Session.Host.Pipeline;
pipeline.Add(new LengthFieldCodec { Size = 4 });
pipeline.Add(new StandardCodec());
};
server.Start();
```
## 最佳实践
- **顺åºè®¾è®¡**:拆包器放在å议解ç 器å‰é¢ï¼›é”™è¯¯é¡ºåºä¼šå¯¼è‡´æ”¶åˆ°æ®‹åŒ…。
- **按连接隔离**:有内部状æ€çš„处ç†å™¨ï¼ˆå¦‚拆包缓å˜ï¼‰å¿…é¡»ä¸ºæ¯æ¡è¿žæŽ¥æ–°å»ºå®žä¾‹ã€‚
- **æå‰ return 时释放**:截æ–é“¾è·¯æ—¶å¿…é¡»é‡Šæ”¾æŒæœ‰çš„ `IPacket`,防æ¢å†…å˜æ³„æ¼ã€‚
- **ä¸è¦åžå¼‚常**:调用 `base.Error` 或 `context.FireError` å‘ä¸‹ä¼ é€’ï¼Œäº¤ç”±æ ¹å¤„ç†å™¨ç»Ÿä¸€å¤„ç†ã€‚
- **继承 Handler è€ŒéžæŽ¥å£**:é¿å…å¿˜è®°ä¼ é€’æ¶ˆæ¯ç»™ä¸‹ä¸€èŠ‚ç‚¹ã€‚
|