C# 自定义网络协议的问题,怎样写协议才可以使发送byte[]数组到服务端后服务端可以轻松解析成键值对形式,或者说怎样写既方便传输又方便解析

cq毕长春 2012-06-14 05:31:54
我自定义一个协议,但是遇到了一个问题,服务端要解析客户端发送过来协议数据,很不方便,协议格式如下

/// <summary>
/// 基础协议
/// </summary>
/// <param name="name">协议名称</param>
/// <param name="command">命令类型[枚举]</param>
/// <param name="protocol">网络协议类型[枚举]</param>
/// <param name="packageBody">消息包体</param>
/// <param name="isNeedReturn">是否需要回馈[枚举]</param>
/// <param name="isNeedEncrypt">是否加密[枚举]</param>
/// <param name="sessionCode">会话码</param>
/// <returns></returns>
public static byte[] GetProtocol(String name, int command, int protocol, byte[] packageBody, Return isNeedReturn, Encrypt isNeedEncrypt, String sessionCode)
{
byte[] p1 = Encoding.Default.GetBytes(name);
byte[] p2 = Encoding.Default.GetBytes(command.ToString());
byte[] p3 = Encoding.Default.GetBytes(protocol.ToString());
byte[] p4 = packageBody;
byte[] p5 = Encoding.Default.GetBytes(isNeedReturn.ToString());
byte[] p6 = Encoding.Default.GetBytes(isNeedEncrypt.ToString());
//这里我把decollator作为的一个分隔符
byte[] decollator = Encoding.Default.GetBytes("≮↔≯");

byte[] result = new byte[p1.Length + p2.Length + p3.Length + p4.Length + p5.Length + p6.Length];

Array.Copy(p1, 0, result, 0, p1.Length);
Array.Copy(decollator, 0, result, p1.Length, decollator.Length);
Array.Copy(p2, 0, result, p1.Length + decollator.Length, p2.Length);
Array.Copy(decollator, 0, result, p1.Length + p2.Length + decollator.Length, decollator.Length);
Array.Copy(p3, 0, result, p1.Length + p2.Length + decollator.Length * 2, p3.Length);
Array.Copy(decollator, 0, result, p1.Length + p2.Length + p3.Length + decollator.Length * 2, decollator.Length);
Array.Copy(p4, 0, result, p1.Length + p2.Length + p3.Length + decollator.Length * 3, p4.Length);
Array.Copy(decollator, 0, result, p1.Length + p2.Length + p3.Length + p4.Length + decollator.Length * 3, decollator.Length);
Array.Copy(p5, 0, result, p1.Length + p2.Length + p3.Length + p4.Length + decollator.Length * 4, p5.Length);
Array.Copy(decollator, 0, result, p1.Length + p2.Length + p3.Length + p4.Length + p5.Length + decollator.Length * 4, decollator.Length);
Array.Copy(p6, 0, result, p1.Length + p2.Length + p3.Length + p4.Length + p5.Length + decollator.Length * 5, p6.Length);
return result;
}

协议传送到服务端后,就根据decollator 将协议内容分割一个数组
我想知道的是,有没有更好的实现方式,不用decollator 就能实现,最好能弄成键值对形式的

...全文
461 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
证明json之类的协议的性能要比xml等不快很多倍 --> 证明json之类的协议的性能要比xml等不知快了很多倍

json比xml快很多倍。现在的计算机非常快,使用json传送命令是非常合适的。用不着搞一大堆“啊~~~~呀~~~~咿咿呀呀~~~~~”的莫名其妙的二进制格式,然后你自己再写一大堆缓慢的所谓解析。
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
/// <summary> /// 基础协议 /// </summary> /// <param name="name">协议名称 </param> /// <param name="command">命令类型[枚举] </param> /// <param name="protocol">网络协议类型[枚举] </param> /// <param name="packageBody">消息包体 </param> /// <param name="isNeedReturn">是否需要回馈[枚举] </param> /// <param name="isNeedEncrypt">是否加密[枚举] </param> /// <param name="sessionCode">会话码 </param> /// <returns> </returns> public static byte[] GetProtocol(String name, int command, int protocol, byte[] packageBody, Return isNeedReturn, Encrypt isNeedEncrypt, String sessionCode) { [/Quote]
你这种原本就是基于二进制的所谓“协议”,我早就不用了。这看似强大,实际上就好像一堆“啊~~~~呀~~~~~咿咿呀呀~~~~~”一样,根本不表义,不容易解析。

如今已经跟十年前不一样了。互联网发展了这么多年,已经有很多的测试证明json之类的协议的性能要比xml等不快很多倍,接近于二进制序列化。而一个json命令可能是这样的
{"fr":"sp1234","to":"svr","type":"EmergencyCommandCenter.SetupAlarm",
"content":{"level":3, "pos_x":114.05, "pos_y":38.9}}
这就是一个命令,哪用得着你那种千篇一律的所谓“通讯格式”?在一个json对象中,type字段的值就说明了content的内容进一步分序列化的类型。

这个json里没有多少废话。
  • 打赏
  • 举报
回复
对于byte[],不要走常规的为了命令而设计的的协议。你可以走独立的http端口进行通讯。

例如在提交用户登录资料命令中要上传一个图片,我们可以将上传图片独立走http post命令,而之前首先使用命令协议去提交除图片以外的其它信息。
cq毕长春 2012-06-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

这不叫“自定义网络协议的问题”,这叫“自定义数据传输结构”。
1、序列和反序列
2、json
3、xml
[/Quote]
因为是第一次接触这个,所以很多地方不懂,呵呵,谢谢你哦
showlie 2012-06-15
  • 打赏
  • 举报
回复
这不叫“自定义网络协议的问题”,这叫“自定义数据传输结构”。
1、序列和反序列
2、json
3、xml
hack_pan 2012-06-15
  • 打赏
  • 举报
回复
3楼 json格式
__天涯寻梦 2012-06-14
  • 打赏
  • 举报
回复
// 发送处理
public static byte[] GetProtocol(string name, int command, int protocol, byte[] packageBody, Return isNeedReturn, Encrypt isNeedEncrypt, String sessionCode)
{
// name 20 字节
// command 4字节
// protocol 4字节
// packageBody长度 4字节
// isNeedReturn 4字节
// isNeedEncrypt 4字节
// sessionCode 20字节

byte[] bytes = new byte[20 + 4 + 4 + 4 + 4 + 4 + 20 + packageBody.Length];
int index = 0;
Encoding.ASCII.GetBytes(name, 0, name.Length, bytes, index);
index += 20;
Array.Copy(BitConverter.GetBytes(command), 0, bytes, index, 4);
index += 4;
Array.Copy(BitConverter.GetBytes(protocol), 0, bytes, index, 4);
index += 4;
Array.Copy(BitConverter.GetBytes(packageBody.Length), 0, bytes, index, 4);
index += 4;
Array.Copy(BitConverter.GetBytes((int)isNeedReturn), 0, bytes, index, 4);
index += 4;
Array.Copy(BitConverter.GetBytes((int)isNeedEncrypt), 0, bytes, index, 4);
index += 4;
Encoding.ASCII.GetBytes(sessionCode, 0, name.Length, bytes, index);
index += 20;
Array.Copy(packageBody, 0, bytes, index, packageBody.Length);

return bytes;
}

// 接收处理
public static void Receive(byte[] bytes)
{
int index = 0;
string name = Encoding.ASCII.GetString(bytes, index, 20);
index += 20;
int command = BitConverter.ToInt32(bytes, index);
index += 4;
int protocol = BitConverter.ToInt32(bytes, index);
index += 4;
int pbength = BitConverter.ToInt32(bytes, index);
index += 4;
Return isNeedReturn = (Return)BitConverter.ToInt32(bytes, index);
index += 4;
Encrypt isNeedEncrypt = (Encrypt)BitConverter.ToInt32(bytes, index);
index += 4;
string sessionCode = Encoding.ASCII.GetString(bytes, index, 20);
index += 20;
byte[] packageBody = new byte[pbength];
Array.Copy(bytes, index, packageBody, 0, pbength);
// ......
}
mwp 2012-06-14
  • 打赏
  • 举报
回复
用XML吧,序列化反序列化都很方便
hack_pan 2012-06-14
  • 打赏
  • 举报
回复
把你要传输的值放到Dictionary<string,string>里面,然后序列化后传输到服务器,服务器接收到后,再反序列化成Dictionary<string,string>,就可以键值对的拿到值

免费送你两段代码

客户端:

static void Main(string[] args)
{
Dictionary<string, string> dics = new Dictionary<string, string>();
dics.Add("username", "007");
dics.Add("password", "@#$");
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1000));
JavaScriptSerializer jss = new JavaScriptSerializer();
string s = jss.Serialize(dics);
socket.Send(Encoding.UTF8.GetBytes(s.ToString()));
socket.Close();
}



服务端

static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1000));
Console.WriteLine("服务器已经启动");
socket.Listen(10);
while (true)
{
Socket ClientSocket = socket.Accept();
byte[] b = new byte[1024 * 2];
int length = ClientSocket.Receive(b);
if (length > 0)
Console.WriteLine("收到来至{0}的请求", ClientSocket.RemoteEndPoint);
string content = Encoding.UTF8.GetString(b, 0, length);
JavaScriptSerializer jss = new JavaScriptSerializer();
Dictionary<string, string> dics = jss.Deserialize<Dictionary<string, string>>(content);
Console.WriteLine("用户名是{0};密码是{1}", dics["username"], dics["password"]);
Console.ReadKey();
}
}
__天涯寻梦 2012-06-14
  • 打赏
  • 举报
回复
String name, int command, int protocol, Return isNeedReturn, Encrypt isNeedEncrypt, String sessionCode
这几个都定死长度
byte[] packageBody
这个发过去时,最前面加4位,记录长度
接收后根据长度分解开
cq毕长春 2012-06-14
  • 打赏
  • 举报
回复
额。别沉了啊

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧