自定义协议封装包头、包体

底层通信消息类,定义消息ID、消息体,和初始化

 1 using System;
 2
 3 /// <summary>
 4 /// 底层通信消息
 5 /// </summary>
 6 public class TSocketMessage : IDisposable
 7 {
 8     /// <summary>
 9     /// 消息ID
10     /// </summary>
11     public int MsgID;
12     /// <summary>
13     /// 消息内容
14     /// </summary>
15     public byte[] MsgBuffer;
16
17     public TSocketMessage(int msgID, byte[] msg)
18     {
19         this.MsgID = msgID;
20         this.MsgBuffer = msg;
21     }
22
23     public void Dispose()
24     {
25         this.Dispose(true);
26         GC.SuppressFinalize(this);
27     }
28
29     protected virtual void Dispose(bool flag1)
30     {
31         if (flag1) { this.MsgBuffer = null; }
32     }
33 }  

消息解析器,封装包头、包体、解析包

  1 using System;
  2 using System.Collections.Generic;
  3 using System.IO;
  4 using System.Text;
  5
  6 // 消息解析器
  7 public class MarshalEndian
  8 {
  9     //用于存储剩余未解析的字节数
 10     private List<byte> _LBuff = new List<byte>(2);
 11     //默认是utf8的编码格式
 12     private UTF8Encoding utf8 = new UTF8Encoding();
 13
 14     //包头1
 15     const Int16 t1 = 0x55;
 16     //包头2
 17     const Int16 t2 = 0xAA;
 18     //字节数常量 两个包头4个字节,一个消息id4个字节,封装消息长度 int32 4个字节
 19     const Int32 ConstLenght = 8;
 20
 21     public void Dispose()
 22     {
 23         this.Dispose(true);
 24         GC.SuppressFinalize(this);
 25     }
 26
 27     protected virtual void Dispose(bool flag1)
 28     {
 29         if (flag1)
 30         {
 31             IDisposable disposable2 = this.utf8 as IDisposable;
 32             if (disposable2 != null) { disposable2.Dispose(); }
 33             IDisposable disposable = this._LBuff as IDisposable;
 34             if (disposable != null) { disposable.Dispose(); }
 35         }
 36     }
 37
 38     public byte[] Encode(TSocketMessage msg)
 39     {
 40         MemoryStream ms = new MemoryStream();
 41         BinaryWriter bw = new BinaryWriter(ms, new UTF8Encoding());
 42         byte[] msgBuffer = msg.MsgBuffer;
 43
 44         #region 封装包头
 45         bw.Write((Int16)t1);
 46         bw.Write((Int16)t2);
 47         #endregion
 48
 49         #region 包协议
 50         if (msgBuffer != null)
 51         {
 52             bw.Write((Int32)(msgBuffer.Length + 4));
 53             bw.Write(msg.MsgID);
 54             bw.Write(msgBuffer);
 55         }
 56         else { bw.Write((Int32)0); }
 57         #endregion
 58
 59         bw.Close();
 60         ms.Close();
 61         bw.Dispose();
 62         ms.Dispose();
 63         return ms.ToArray();
 64     }
 65
 66     public List<TSocketMessage> GetDcAppMess(byte[] buff, int len)
 67     {
 68         //拷贝本次的有效字节
 69         byte[] _b = new byte[len];
 70         Array.Copy(buff, 0, _b, 0, _b.Length);
 71         buff = _b;
 72         if (this._LBuff.Count > 0)
 73         {
 74             //拷贝之前遗留的字节
 75             this._LBuff.AddRange(_b);
 76             buff = this._LBuff.ToArray();
 77             this._LBuff.Clear();
 78             this._LBuff = new List<byte>(2);
 79         }
 80
 81         List<TSocketMessage> list = new List<TSocketMessage>();
 82         MemoryStream ms = new MemoryStream(buff);
 83         BinaryReader buffers = new BinaryReader(ms, this.utf8);
 84         try
 85         {
 86             byte[] _buff;
 87             Label_00983:
 88
 89             #region 包头读取
 90             //循环读取包头
 91             //判断本次解析的字节是否满足常量字节数
 92             if ((buffers.BaseStream.Length - buffers.BaseStream.Position) < ConstLenght)
 93             {
 94                 _buff = buffers.ReadBytes((int)(buffers.BaseStream.Length - buffers.BaseStream.Position));
 95                 this._LBuff.AddRange(_buff);
 96                 return list;
 97             }
 98             Int16 tt1 = buffers.ReadInt16();
 99             Int16 tt2 = buffers.ReadInt16();
100             if (!(tt1 == t1 && tt2 == t2))
101             {
102                 long ttttt = buffers.BaseStream.Seek(-3, SeekOrigin.Current);
103                 goto Label_00983;
104             }
105             #endregion
106
107             #region 包协议
108             int offset = buffers.ReadInt32();
109             #endregion
110
111             #region 包解析
112             //剩余字节数大于本次需要读取的字节数
113             if (offset <= (buffers.BaseStream.Length - buffers.BaseStream.Position))
114             {
115                 int msgID = buffers.ReadInt32();
116                 _buff = buffers.ReadBytes(offset - 4);
117                 list.Add(new TSocketMessage(msgID, _buff));
118                 if ((buffers.BaseStream.Length - buffers.BaseStream.Position) > 0)
119                 {
120                     goto Label_00983;
121                 }
122             }
123             else
124             {
125                 //剩余字节数刚好小于本次读取的字节数 存起来,等待接受剩余字节数一起解析
126                 _buff = buffers.ReadBytes((int)(buffers.BaseStream.Length - buffers.BaseStream.Position + ConstLenght));
127                 this._LBuff.AddRange(_buff);
128             }
129             #endregion
130         }
131         catch (Exception ex) { Console.WriteLine(ex); }
132         finally
133         {
134             if (buffers != null) { buffers.Dispose(); }
135             buffers.Close();
136             if (buffers != null) { buffers.Dispose(); }
137             ms.Close();
138             if (ms != null) { ms.Dispose(); }
139         }
140         return list;
141     }
142 }  
时间: 2024-10-21 01:37:13

自定义协议封装包头、包体的相关文章

mina的编码和解码以及断包的处理,发送自定义协议,仿qq聊天,发送xml或json和

最近一段时间以来,mina很火,和移动开发一样,异常的火爆.前面写了几篇移动开发的文章,都还不错,你们的鼓励就是我最大的动力.好了,废话少说.我们来看下tcp通讯吧. tcp通讯对于java来说是很简单的.就是socket,也就是大家常说的套接字.大家不要把它看的很难.说白了tcp通讯其实就是数据流的读写.一条输入流,一条输出流.分别复杂发消息和接收消息. 明白了这些,ok,我们来看看我写的例子吧.先看服务器端的测试类的源码: package com.minaqq.test; import co

在Java语言中调用存储过程、存储函数、包头、包体

需要拷贝连接Oracle的jar包,路径如下图所示: 连接Oracle数据库的代码: package demo.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { private static Stri

如何将自定义标签封装成一个Jar包

当我们在一个web应用中开发好一些自定义标签的时候,这些自定义标签通常有标签处理器Java类,和一个描述这些标签tld文件,如果我们想在以后别的web工程中还能用上这些标签,可以将这些自定义标签封装在一个JAR包中,正如JSTL标签库一样. 我们现在准备将web应用中开发好的自定义标签封装成jar包,这些自定义标签的两个文件如下图所示:   要想封装成专门的jar包,我们需要另外建一个Java工程,注意是Java工程,不是web工程,这里设置该Java工程名称为“simpletag”,接着在该工

swoole入门教程05-Swoole的自定义协议功能的使用

环境说明: 系统:Ubuntu14.04 (安装教程包括CentOS6.5) PHP版本:PHP-5.5.10 swoole版本:1.7.8-alpha 1.为什么要提供自定义协议 熟悉TCP通信的朋友都会知道,TCP是一个流式协议.客户端向服务器发送的一段数据,可能并不会被服务器一次就完整的收到;客户端向服务器发送的多段数据,可能服务器一次就收到了全部的数据.而实际应用中,我们希望在服务器端能一次接收一段完整的数据,不多也不少.传统的TCP服务器中,往往需要由程序员维护一个缓存区,先将读到的数

Python爬虫最为核心的HTTP协议解析,及自定义协议的分析!

机器之间的协议就是机器通信的语法,只有按照这种语法发来的信息,机器之间才能相互理解内容,也可以理解为信息的一种格式. HTTP/IP协议是互联网最为重要的协议,没有HTTP/IP协议,也就没有互联跟不会有网,对于爬虫而言一切数据.请求都是围绕HTTP协议展开.但是在python实现的网络爬虫中都是使用封装好了的请求库如:requests.scrapy.urllib等,这些是对socket的封装,而socket是除了机器语言外最底层的协议. HTTP是公认的协议,但是并不是所有的终端通信都使用HT

物联网架构成长之路(35)-利用Netty解析物联网自定义协议

一.前言 前面博客大部分介绍了基于EMQ中间件,通信协议使用的是MQTT,而传输的数据为纯文本数据,采用JSON格式.这种方式,大部分一看就知道是熟悉Web开发.软件开发的人喜欢用的方式.由于我也是做web软件开发的,也是比较喜欢这种方式.阿里的物联网平台,也是推荐这种方式.但是,但是做惯硬件开发,嵌入式开发就比较喜欢用裸TCP-Socket连接.采用的是二进制协议.基于此大部分应用场合为了兼容旧设备,就需要单独开发一个TCP服务器的网关.这里使用以前学过的,也是比较流行的Netty框架. 话不

第13章 TCP编程(3)_基于自定义协议的多进程模型

5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 char head[10];//TLV中的T unsigned int checkNum; //校验码 unsigned int cbSizeContent; //协议体的长度 //协议体部 char buff[512]; //数据 }MSG; (2)自定义读写函数 ①extern int write_msg(int sockfd, cha

第13章 TCP编程(4)_基于自定义协议的多线程模型

7. 基于自定义协议的多线程模型 (1)服务端编程 ①主线程负责调用accept与客户端连接 ②当接受客户端连接后,创建子线程来服务客户端,以处理多客户端的并发访问. ③服务端接到的客户端信息后,回显给客户端 (2)客户端编程 ①从键盘输入信息,并发送给服务端 ②接收来自服务端的信息 //msg.h与前一节相同 #ifndef __MSG_H__ #define __MSG_H__ #include <sys/types.h> //求结构体中成员变量的偏移地址 #define OFFSET(T

wireshark插件开发 - 自定义协议

虽然wireshark自带了很多知名协议的解析插件,譬如HTTP.DHCP等等,然而在实际应用环境中,有不少软件之间的通信协议都是私有的,如游戏客户端和服务器之间的交互协议通常都是私有的,wireshark无法具体解析出各种字段之间的含义,只能显示接收到的二进制数据,给协议的分析和问题的排查带来了一定的困难,尤其是协议内容比较复杂时. 本文一个自定义的简单协议入手,分析如何基于wireshark开发自定义协议分析插件. 1.1. 概述 本书使用Go语言来描述协议的交互过程.Go由Google出品