消息系统技术文档

消息系统技术文档

概述

本文档详细说明了如何在现有的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
=====================

八、添加新消息类型的通用步骤

基于李宏利消息的实现经验,添加新消息类型的通用步骤:

  1. 定义消息类

    • 继承 MessageBase
    • 分配唯一的消息ID
    • 实现 BuildPackage()ParsePackage() 方法
  2. 注册消息ID

    • EnumDispatchMessageID 中添加新的枚举值
  3. 添加消息路由

    • CommunicationClientReceivePackage.cs 中添加处理分支
  4. 实现发送逻辑

    • 在客户端应用中添加发送功能
  5. 实现接收处理

    • 在事件处理器中添加消息处理逻辑
  6. 测试验证

    • 编译所有项目
    • 运行服务端和客户端进行测试

九、注意事项

  1. 消息ID唯一性: 确保每种消息类型都有唯一的消息ID
  2. 序列化格式 : 保持 BuildPackage()ParsePackage() 方法的格式一致性
  3. 错误处理: 在消息解析和处理过程中添加适当的异常处理
  4. 项目依赖: 确保所有项目引用路径正确,能够正常编译
  5. 向后兼容: 新增消息类型不应影响现有消息处理逻辑

十、编译和部署指南

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

本文档记录了李消息系统的完整实现过程,可作为后续添加其他消息类型的参考模板。

相关推荐
云知谷1 小时前
【HTML】网络数据是如何渲染成HTML网页页面显示的
开发语言·网络·计算机网络·html
呉師傅6 小时前
关于联想ThinkCentre M950t-N000 M大师电脑恢复预装系统镜像遇到的一点问题
运维·网络·windows·电脑
代码AI弗森6 小时前
无状态的智慧:从 HTTP 到大模型的系统进化论
网络·网络协议·http
酷熊代理6 小时前
安卓手机 IP 切换指南:告别卡顿,轻松换 IP
网络·网络协议·tcp/ip·socks5
月上柳青7 小时前
快速创建无线AP热点
网络·智能路由器
K_i1348 小时前
云原生网络基础:IP、端口与网关实战
网络·ip·接口隔离原则
m0_651593918 小时前
Netty网络架构与Reactor模式深度解析
网络·架构
大面积秃头9 小时前
Http基础协议和解析
网络·网络协议·http
我也要当昏君10 小时前
6.3 文件传输协议 (答案见原书 P277)
网络
开发游戏的老王10 小时前
虚幻引擎虚拟制片入门教程 之 Sequencer 常用技巧
游戏引擎·虚幻