我自定义一个协议,但是遇到了一个问题,服务端要解析客户端发送过来协议数据,很不方便,协议格式如下/// <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 就能实现,最好能弄成键值对形式的

解决方案 »

  1.   

    String name, int command, int protocol, Return isNeedReturn, Encrypt isNeedEncrypt, String sessionCode 
    这几个都定死长度
    byte[] packageBody
    这个发过去时,最前面加4位,记录长度
    接收后根据长度分解开
      

  2.   

    把你要传输的值放到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();
                }
            }
      

  3.   

    用XML吧,序列化反序列化都很方便
      

  4.   

    // 发送处理
    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);
        // ......
    }
      

  5.   

    对于byte[],不要走常规的为了命令而设计的的协议。你可以走独立的http端口进行通讯。例如在提交用户登录资料命令中要上传一个图片,我们可以将上传图片独立走http post命令,而之前首先使用命令协议去提交除图片以外的其它信息。
      

  6.   

    你这种原本就是基于二进制的所谓“协议”,我早就不用了。这看似强大,实际上就好像一堆“啊~~~~呀~~~~~咿咿呀呀~~~~~”一样,根本不表义,不容易解析。如今已经跟十年前不一样了。互联网发展了这么多年,已经有很多的测试证明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里没有多少废话。
      

  7.   

    证明json之类的协议的性能要比xml等不快很多倍  --> 证明json之类的协议的性能要比xml等不知快了很多倍json比xml快很多倍。现在的计算机非常快,使用json传送命令是非常合适的。用不着搞一大堆“啊~~~~呀~~~~咿咿呀呀~~~~~”的莫名其妙的二进制格式,然后你自己再写一大堆缓慢的所谓解析。
      

  8.   

    这不叫“自定义网络协议的问题”,这叫“自定义数据传输结构”。
    1、序列和反序列
    2、json
    3、xml