Silverlight MMORPG WebGame游戏设计(三)-----Server和Client的暗号

          silverlight客户端和服务端就像一对被微软家长阻隔的恋人,服务端提供了安全策略文件这个硬通货,就如同男人买了房,一切都开绿灯了。

          这对恋人终于可以约会了,他们如何飞鸿传书呢?是写在枫叶上,还是封上了火漆的羊皮卷里。其实每个民族有自己的风俗,每个程序员也可以写出不同的协议。

          我们把他们通讯的基本单位抽象成Message,你可以这么描述它:

         

ExpandedBlockStart.gif Message类
   public   class  Message
    {

     /// <summary>
        /// 处理信息的socket对象
        /// </summary>
        public System.Net.Sockets.Socket clientSocket { get; set; }
        /// <summary>
        /// 消息内容
        /// </summary>
        public byte[] Content{get;set;}
        /// <summary>
        /// 消息长度
        /// </summary>
        public int Size{get;set;}
        /// <summary>
        /// 消息状态
        /// </summary>
        public byte Flag{get;set;}
        /// <summary>
        /// 消息类别
        /// </summary>
        public byte Class {get;set;}
    
   }

       也就是说服务端和客户端通讯的时候是一个个message为单位发送过去的,但是传输过程中,服务端不可能刚好完整就接到了一个Message,也可能接收到半个Message,所以需要加一个size来判断是否Message读取完毕。

       在封装Message的时候我们要写一个MessageStream类来方便封装Message,一般网络游戏服务端和客户端都会有这样的类,来从byte数组中把数据读出,或者把数据写入到byte数组中,这样的类里一般都有ReadInt,ReadByte,ReadString,ReadFloat,WriteInt,WriteByte , WriteString,WriteFloat 这样的方法。

       这里我给出一个很简单的封装类MessageStream

       

ExpandedBlockStart.gif MessageStream
    public   class  MessageStream
    {
        
private   byte [] buffer;
        
private   int  position;
        
private   int  length;
        
private   int  capacity;

        
public  MessageStream()
        {
            buffer 
=   new   byte [ 0 ];
            position 
=   0 ;
            length 
=   0 ;
            capacity 
=   0 ;
        }

        
private   byte  ReadByte()
        {
            
if  ( this .position  >=   this .length)
            {
                
return   0 ;
            }
            
return   this .buffer[ this .position ++ ];
        }

        
private   int  ReadInt()
        {
            
int  num  =   this .position  +=   4 ;
            
if  (num  >   this .length)
            {
                
this .position  =   this .length;
                
return   - 1 ;
            }
            
return  ((( this .buffer[num  -   4 |  ( this .buffer[num  -   3 <<   8 ))  |  ( this .buffer[num  -   2 <<   0x10 ))  |  ( this .buffer[num  -   1 <<   0x18 ));
        }

        
private   byte [] ReadBytes( int  count)
        {
            
int  num  =   this .length  -   this .position;
            
if  (num  >  count)
            {
                num 
=  count;
            }
            
if  (num  <=   0 )
            {
                
return   null ;
            }
            
byte [] buffer  =   new   byte [num];
            
if  (num  <=   8 )
            {
                
int  num2  =  num;
                
while  ( -- num2  >=   0 )
                {
                    buffer[num2] 
=   this .buffer[ this .position  +  num2];
                }
            }
            
else
            {
                Buffer.BlockCopy(
this .buffer,  this .position, buffer,  0 , num);
            }
            
this .position  +=  num;
            
return  buffer;
        }

        
public   bool  Read( out  Message message)
        {
            message 
=   null ;
            position 
=   0 ;
            
if  (length  >   6 )
            {
                message 
=   new  Message();
                message.Class 
=  ReadByte();
                message.Flag 
=  ReadByte();
                message.Size 
=  ReadInt();
                
if  (message.Size  <=   0   ||  message.Size  <=  length  -  position)
                {
                    
if  (message.Size  >   0 )
                    {
                        message.Content 
=  ReadBytes(message.Size);
                    }
                    Remove(message.Size 
+   6 );
                    
return   true ;
                }
                
else
                {
                    message 
=   null ;
                    
return   false ;
                }
            }
            
else
            {
                
return   false ;
            }
        }
         
        
private   void  EnsureCapacity( int  value)
        {
            
if  (value  <=   this .capacity)
                
return ;
            
int  num1  =  value;
            
if  (num1  <   0x100 )
                num1 
=   0x100 ;
            
if  (num1  <  ( this .capacity  *   2 ))
                num1 
=   this .capacity  *   2 ;
            
byte [] buffer1  =   new   byte [num1];
            
if  ( this .length  >   0 )
                Buffer.BlockCopy(
this .buffer,  0 , buffer1,  0 this .length);
            
this .buffer  =  buffer1;
            
this .capacity  =  num1;
        }

          public void Write(byte[] intbuffer, int offset, int count)
        {
            if (intbuffer.Length - offset < count)
            {
                count = intbuffer.Length - offset;
            }
            EnsureCapacity(length + count);
            Array.Clear(this.buffer, length, capacity - length);
            Buffer.BlockCopy(intbuffer, offset, this.buffer, length, count);
            length += count;
        }
         private   void  Remove( int  count)
        {
            
if  (length  >=  count)
            {
                Buffer.BlockCopy(buffer, count, buffer, 
0 , length  -  count);
                length 
-=  count;
                Array.Clear(buffer, length, capacity 
-  length);
            }
            
else
            {
                length 
=   0 ;
                Array.Clear(buffer, 
0 , capacity);
            }
        }
    }

 

 

      有了MessageStream这样的辅助类了,我们就可以在Message类加上一个添加消息和一个读取消息的方法

    

ExpandedBlockStart.gif 写入和读取Message的方法
    ///   <summary>
        
///  把消息对象转化为byte[]
        
///   </summary>
        
///   <returns></returns>
         public   byte [] ToBytes()
        {
            
byte [] _byte;
            
using  (MemoryStream mem  =   new  MemoryStream())
            {
                BinaryWriter writer 
=   new  BinaryWriter(mem);
                writer.Write(Class);
                writer.Write(Flag);
                writer.Write(Size);
                
if  (Size  >   0 )
                {
                    writer.Write(Content);
                }
                _byte 
=  mem.ToArray();
                writer.Close();
            }
            
return  _byte;
        }
        
///   <summary>
        
///  从byte[]中读取一个message对象
        
///   </summary>
        
///   <param name="Buffer"></param>
        
///   <returns></returns>
         public   static  Message FromBytes( byte [] Buffer)
        {
            Message message 
=   new  Message();
            
using  (MemoryStream mem  =   new  MemoryStream(Buffer))
            {
                BinaryReader reader 
=   new  BinaryReader(mem);
                message.Class 
=  reader.ReadByte();
                message.Flag 
=  reader.ReadByte();
                message.Size 
=  reader.ReadInt32();
                
if  (message.Size  >   0 )
                {
                    message.Content 
=  reader.ReadBytes(message.Size);
                }
                reader.Close();
            }
            
return  message;
        }

 

         有了MessageStream,Message这两个忠实的仆人的帮助,SL客户端和服务端这对恋人就不用像发摩尔斯电码那样来交流了,他们只要口述旨意,让两个仆人去滴滴答答发电报就行了。见过电影里发电报的都知道,有人发电报,就有人收电报。所以客户端有这样两个仆人,服务端也得有这样两个仆人。那我们程序员的话说SL客户端有这样两个类,同样服务端也要有这样两个类。

        当然以上我只是简单描述了一个Message对象,在真实项目里Message对象没这么简单。我举个例子:

       

格式:

循环

循环

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

不定长

消息个数

消息总长度

用户UID

用户CID

单个消息指针起始位置

消息内容

消息内容协议

0

1

2

3

4

5

不定长

消息Group

消息具体type

时间戳

消息逻辑内容

 

 HTTP命令区:

       Message1 (byte) 消息个数

       MessageLength: 120 (int) byte数组总长度

       UID:2 (int)用户标识ID

       CID 1 (int)用户子ID

       MessagePointer: 0 (short) 单个消息指针起始位置

HTTP 内容区:

       GroupID:1 (byte) 消息组ID

       GroupType:1 (byte) 消息组具体操作ID

       Timestamp: 0 (int) 时间戳

       ContentLength: 10 (short) 消息内容的长度(根据内容来定类型)

Content:”你好吗?” (string) 消息内容

    这种协议一次可以发多个消息体,只带一个消息头,也带上用户的信息,因为mmorpg里参与最多是用户,发的消息也和用户编号直接相关。

     有兴趣的同学可以写下这个种协议的写入和读取。到此为止,是不是服务端和客户端就可以踏入婚姻的殿堂了,可惜还远没有呢,这是各自准备了两个伴郎和伴娘,客户端急了:“老公,你房子什么时候才装修好啊?”

      大家看到这里也在想,服务端什么时候才可以搭建好啊,就像装房子一样,急不得,还有好多问题。请看下一篇:

      Silverlight MMORG WebGame游戏设计(四)-----Client:Server!房子啥时候装好?我急嫁人啊!

转载于:https://www.cnblogs.com/wangergo/archive/2010/04/10/1708879.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值