解决方案 »

  1.   

    比如说你使用 NewtoneSoft.Json 来进行 json 跟 .net 内部对象的转换处理。假设我们收到了一个字符串
    {  "SeqNum" : 10023,
       "CmdType“ : "EnteringRoom",
       "Content" : {  "RoomId" : "1293883",
                            "Account" : "abc",
                            "Pwd" : "8899ksdkf82",
                            "Expire" : 5
                         }
    }这里,首先,所有的命令都有 SeqNum 表示序号,"Type"表示命令类型,"Content” 表示具体的命令体内容。不同命令,其格式上就是 Content 部分 有所不同。解析时,首先使用 var x = JObject.Parse(str); 来得到整个命令,然后 根据 (string)x["CmdType“]  的值,到你的命令字典中找到对应的具体命令(是一个class)在 .net 程序内部声明 Type。
    var cmd = x["Content"].ToObject(type);
    现在,我们就把传过来的命令解析出一个独立的 EnteringRoom 类型对象,并且赋值给变量 cmd 了。执行命令更为简单。执行命令就是“输入object,输出object”的函数。在你的程序一开始,需要声明public static Dictionary<Type, Func<object,object>> commands = new  Dictionary<Type, Func<object,object>>(); 的一个集合,并且在程序一开始注册给这个集合。例如private object Enter(object cmd)
    {
        ....
    }commands.Add(typeof(EnteringRoom, Enter);    //注册 Enter 方法负责处理以 EnteringRoom 类型命令
    那么根据上述cmd,就可以找到处理程序并进行处理,例如Func<object,object> p;
    object result;
    if(commands.TryGetCalue(cmd.GetType(), out p))
        result = p(cmd);
    else
        throw new Exception(string.Format("找不到 {0} 的命令处理程序。", cmd.GetType().FullName));
        
    得到返回值之后,再把它封装为一个完整的命令,返回给发送端即可。例如我们规定返回信息的 SeqNum编号为负数表示返回,就可以写var y = new Commnd{ 
                    SeqNum = -(int)x["SeqNum"],
                    CmdType = result.GetType().Name,
                    Content = JObject.FromObject(result).ToString()
            };
    最后把这个命令 y 进行 json 序列化,发送给对方作为返回消息。
      

  2.   

    最后我要补充一点儿,上面说的是逻辑上的核心设计概念,这部分是最有特点的,每一个系统的设计方式可以不一样(我们的肯定也比这个复杂一点)。这里并没有什么“包”的概念。因为“包”是一个相对来说没有技术含量的封装层,而上面说的都是包承载的内容用于整个业务处理的流程。对于没有什么技术含量的那层“封装”,才是针对简单的 byte[] 传递的。在你接收数据时,总是会“粘包”的,因此我们可以这样规定包的格式(举例):1. 前4个字节表示整个包的长度;2. 然后是上述 y 内容的 json 字符串。这就行了。所以“包”本身没有技术含量,不过就是用来让你接收端不会“粘包”的。真正有技术含量的函是对于包中的内容的解析机制。
      

  3.   

    嗯,上面我的例子中有一行代码应该是写错了,
            Content = JObject.FromObject(result).ToString()
    应该写为
            Content = JObject.FromObject(result)
    才对,因为我在举一开始的接收端的例子时,对于 Content 属性,是做为 JObject 类型,而不是作为 string 类型处理的。
      

  4.   

    先决定C和S用什么协议链接。
    最简单的,S就是数据库,C直接用ADO.NET访问数据库就好了。
    其次,S如果你是个Web站点,那么就是用http,不嫌麻烦(或者为了兼容已有网站)你的C就模拟http提交的表单来和web站点交互,当然也可以自己定义首发的内容,如楼上那些方式。也可以用现成的WebService/WCF来交互处理。
    最麻烦,某些场景下也是必须的就是用TCP/UDP通信,这样你自己定义两段收发的命令就好了。比如C发过去1,S就知道要注册用户了。