消息系统技术文档
概述
本文档详细说明了如何在现有的LHD通信系统中添加自己的消息类型,包括消息的发送、接收、解析和处理的完整流程。
系统架构
消息流程架构图
客户端B 服务端 通信框架 客户端A 消息解析 TCP接收 消息ID匹配 0x0006 ParsePackage 触发ReceiveDefaultMessage事件 反射获取属性 显示消息内容 TCP监听 MessageServerApp 消息路由 转发到目标客户端 消息序列化 MessageCommunicationClient TCP发送 发送李宏利消息 MessageClientApp 创建Lihongli2Message 调用SendMessage
时序图
客户端A MessageServerApp 客户端B 发送李宏利消息(0x0006) 消息路由处理 转发消息到客户端B 消息解析(ParsePackage) 事件触发(ReceiveDefaultMessage) 显示消息内容 客户端A MessageServerApp 客户端B
一、项目结构与依赖关系
1.1 核心项目
- Lihongli2Message: 消息类型定义项目
- MessageCommunicationServer: 服务端通信组件
- MessageCommunicationClient: 客户端通信组件
- MessageServerApp: 服务端应用程序
- MessageClientApp: 客户端应用程序
1.2 依赖关系修复
在添加李宏利消息类型过程中,修复了以下依赖关系问题:
xml
<!-- Demos/HomeWork/Lihongli2Message/Lihongli2Message.csproj -->
<ItemGroup>
<!-- 修复前:路径错误 -->
<ProjectReference Include="..\..\Configuration\SystemConst\SystemConst.csproj" />
<!-- 修复后:正确的相对路径 -->
<ProjectReference Include="..\..\..\Configuration\SystemConst\SystemConst.csproj" />
<ProjectReference Include="..\..\..\MessageCommunication\CommunicationTCPMessage\CommunicationTCPMessage.csproj" />
</ItemGroup>
二、消息类型实现
2.1 消息类定义
文件 : Demos/HomeWork/Lihongli2Message/Lihongli2Message.cs
csharp
using System;
using System.Text;
using CommunicationMessage;
namespace CommunicationMessage.MessageObject
{
[Serializable]
public class Lihongli2Message : MessageBase
{
public string SenderName { get; set; } = "";
public string MessageContent { get; set; } = "";
public DateTime SendTime { get; set; }
public string MessageType { get; set; } = "李宏利消息";
// 关键:使用消息ID 0x0006 和正常消息类型
public Lihongli2Message() : base((byte)EnumDispatchMessageTypeID.EnumNornalMessage, 0x0006)
{
this.SendTime = DateTime.Now;
this.DataLength = 0;
}
// 消息序列化
public override byte[] BuildPackage()
{
string messageString = $"{SenderName}|{MessageContent}|{SendTime:yyyy-MM-dd HH:mm:ss}|{MessageType}";
byte[] data = Encoding.UTF8.GetBytes(messageString);
this.DataLength = data.Length;
return data;
}
// 消息反序列化
public override void ParsePackage(byte[] data, int startIndex)
{
try
{
if (data == null || data.Length < startIndex + DataLength)
{
return;
}
byte[] messageData = new byte[DataLength];
Array.Copy(data, startIndex, messageData, 0, DataLength);
var message = FromBytes(messageData);
if (message != null)
{
this.SenderName = message.SenderName;
this.MessageContent = message.MessageContent;
this.SendTime = message.SendTime;
this.MessageType = message.MessageType;
}
}
catch (Exception ex)
{
Console.WriteLine($"解析李宏利消息包失败: {ex.Message}");
}
}
}
}
2.2 消息ID注册
文件 : MessageCommunication/CommunicationTCPMessage/EnumDispatchMessageID.cs
csharp
public enum EnumDispatchMessageID : UInt32
{
// 其他消息ID...
//lihongli消息 - 关键:分配唯一ID
EnumMessagelihongli = 0x0006,
}
三、消息发送实现
3.1 客户端发送逻辑
文件 : MessageCommunication/MessageClientApp/Program.cs
csharp
private static void SendLihongli2Message()
{
Console.WriteLine("=== 发送李宏利消息 ===");
// 收集用户输入
Console.Write("请输入发送者姓名: ");
string senderName = Console.ReadLine() ?? "匿名";
Console.Write("请输入消息内容: ");
string content = Console.ReadLine() ?? "";
Console.Write("请输入消息类型 (默认:李宏利消息): ");
string messageType = Console.ReadLine()?.Trim() ?? "李宏利消息";
// 创建并发送消息
var message = new Lihongli2Message(senderName, content, messageType);
ServerApp.SendMessage((uint)EnumTCPCommunicationChannel.ClientView, message);
Console.WriteLine($"发送李宏利消息: {message.ToJsonString()}");
}
四、消息接收与路由
4.1 消息路由机制
文件 : MessageCommunication/MessageCommunicationClient/CommunicationClientReceivePackage.cs
csharp
private void ReceivePackage(MessagePackage package)
{
// 提取消息码
uint messageCode = package.MessageCode & 0x00FFFFFF;
Console.WriteLine($"收到消息包: MessageCode=0x{package.MessageCode:X}, 处理后=0x{messageCode:X}");
switch ((EnumDispatchMessageID)messageCode)
{
case EnumDispatchMessageID.EnumMessagelihongli: // 李宏利消息路由
Console.WriteLine("✓ 匹配到李宏利消息,开始处理...");
if (ReceiveDefaultMessage != null)
{
// 创建消息对象并设置属性
Lihongli2Message msg = new Lihongli2Message()
{
MessageSource = package.MessageSource,
MessageTarget = package.MessageTarget,
DataLength = package.DataLength,
};
// 解析消息数据
msg.ParsePackage(package.MessageData, 0);
Console.WriteLine("✓ 李宏利消息解析完成,触发事件");
// 触发事件处理
ReceiveDefaultMessage(msg);
}
break;
// 其他消息类型处理...
}
}
五、消息处理与显示
5.1 事件处理器
文件 : MessageCommunication/MessageClientApp/Program.cs
csharp
private static void ServerApp_ReceiveDefaultMessage(MessageBase message)
{
try
{
Console.WriteLine($"事件处理器被调用,消息类型: {message.GetType().Name}");
Console.WriteLine($"消息码: 0x{message.GetMessageCode():X}");
// 检查是否是李消息
if (message.GetMessageCode() == 0x0006) // Lihongli2Message的消息码
{
Console.WriteLine("✓ 消息码匹配,检查消息类型...");
// 使用反射安全地访问属性
var senderNameProperty = message.GetType().GetProperty("SenderName");
var messageContentProperty = message.GetType().GetProperty("MessageContent");
var sendTimeProperty = message.GetType().GetProperty("SendTime");
var messageTypeProperty = message.GetType().GetProperty("MessageType");
if (senderNameProperty != null && messageContentProperty != null &&
sendTimeProperty != null && messageTypeProperty != null)
{
Console.WriteLine("✓ 使用反射成功获取消息属性");
// 显示消息内容
Console.WriteLine("\n=== 收到李宏利消息 ===");
Console.WriteLine($"发送者: {senderNameProperty.GetValue(message)}");
Console.WriteLine($"内容: {messageContentProperty.GetValue(message)}");
Console.WriteLine($"时间: {sendTimeProperty.GetValue(message)}");
Console.WriteLine($"类型: {messageTypeProperty.GetValue(message)}");
Console.WriteLine("=====================");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"处理李消息时发生错误: {ex.Message}");
}
}
六、关键修改文件清单
6.1 新增文件
Demos/HomeWork/Lihongli2Message/Lihongli2Message.cs
- 消息类定义Demos/HomeWork/Lihongli2Message/Lihongli2Message.csproj
- 项目配置
6.2 修改的文件
文件路径 | 修改内容 | 说明 |
---|---|---|
MessageCommunication/CommunicationTCPMessage/EnumDispatchMessageID.cs |
添加 EnumMessagelihongli = 0x0006 |
注册消息ID |
MessageCommunication/MessageCommunicationClient/CommunicationClientReceivePackage.cs |
添加李宏利消息处理分支 | 消息路由 |
MessageCommunication/MessageClientApp/Program.cs |
添加发送和接收处理逻辑 | 客户端功能 |
MessageCommunication/MessageServerApp/Program.cs |
添加李宏利消息创建示例 | 服务端功能 |
6.3 项目引用修复
- 修复了
Lihongli2Message.csproj
中的相对路径引用 - 确保所有依赖项目能够正确编译和链接
七、测试验证
7.1 成功运行日志示例
Input debug command to show info...
收到消息包: MessageCode=0x6, 处理后=0x6
✓ 匹配到李宏利消息,开始处理...
ParsePackage: data长度=54, startIndex=0, DataLength=54
ParsePackage: 复制的数据长度=54
ParsePackage: 原始数据=李宏利|11111111111111111111|2025-08-04 22:57:37|123
ParsePackage: FromBytes成功,设置属性
ParsePackage: 设置完成 - SenderName='李宏利', Content='11111111111111111111'
✓ 李宏利消息解析完成,触发事件
事件处理器被调用,消息类型: Lihongli2Message
消息码: 0x6
✓ 消息码匹配,检查消息类型...
✓ 使用反射成功获取消息属性
=== 收到李宏利消息 ===
发送者: 李宏利
内容: 11111111111111111111
时间: 2025/8/4 22:57:37
类型: 123
=====================
八、添加新消息类型的通用步骤
基于李宏利消息的实现经验,添加新消息类型的通用步骤:
-
定义消息类
- 继承
MessageBase
- 分配唯一的消息ID
- 实现
BuildPackage()
和ParsePackage()
方法
- 继承
-
注册消息ID
- 在
EnumDispatchMessageID
中添加新的枚举值
- 在
-
添加消息路由
- 在
CommunicationClientReceivePackage.cs
中添加处理分支
- 在
-
实现发送逻辑
- 在客户端应用中添加发送功能
-
实现接收处理
- 在事件处理器中添加消息处理逻辑
-
测试验证
- 编译所有项目
- 运行服务端和客户端进行测试
九、注意事项
- 消息ID唯一性: 确保每种消息类型都有唯一的消息ID
- 序列化格式 : 保持
BuildPackage()
和ParsePackage()
方法的格式一致性 - 错误处理: 在消息解析和处理过程中添加适当的异常处理
- 项目依赖: 确保所有项目引用路径正确,能够正常编译
- 向后兼容: 新增消息类型不应影响现有消息处理逻辑
十、编译和部署指南
10.1 编译顺序
bash
# 1. 编译依赖项目
dotnet build Configuration/SystemConst/SystemConst.csproj
dotnet build MessageCommunication/CommunicationTCPMessage/CommunicationTCPMessage.csproj
# 2. 编译消息类项目
dotnet build Demos/HomeWork/Lihongli2Message/Lihongli2Message.csproj
# 3. 编译应用程序
dotnet build MessageCommunication/MessageServerApp/MessageServerApp.csproj
dotnet build MessageCommunication/MessageClientApp/MessageClientApp.csproj
# 4. 编译整个解决方案
dotnet build LHDDispatch.sln
10.2 运行说明
bash
# 启动服务端
dotnet run --project MessageCommunication/MessageServerApp/MessageServerApp.csproj
# 启动客户端(在新的终端窗口中)
dotnet run --project MessageCommunication/MessageClientApp/MessageClientApp.csproj
文档版本 : 1.0
创建时间 : 2025年8月4日
最后更新 : 2025年8月4日
文档位置 : D:\APPfile\Cshape_learn\LHD\李宏利消息系统技术文档.md
本文档记录了李消息系统的完整实现过程,可作为后续添加其他消息类型的参考模板。