Unity3D使用TCP/IP协议,传递protocol buffer消息protobuf-net

原文:http://my.oschina.net/faint/blog/296785

经过测试是可行的。

第一部分 dll

1 下面大多数内容,都是使用c#编译的dll来实现的。

2 编译为dll后,要拖放到unity3d的Assets里面,才能using到。

3 有以下类似错误,就是使用了非.net 2.0编译的dll。注意项目必须是在.net 2.0版本编译的才能正常在unity3d当中使用。

Unhandled Exception: System.TypeLoadException: Could not load type 'System.Runtime.Versioning.TargetFrameworkAttribute' from assembly 'MyModel'

4 应该不能用MonoDevelop编译下面会提到的Serializer部分(编译不出dll,会报错)。需用vs编译。

 

第二部分 tcp/ip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using  System;
using  System.IO;
using  System.Net.Sockets;
 
namespace  TcpConnector{
 
     public  struct  Msg {
         public  int  Type;
         public  int  Size;
         public  byte [] Content;
     }
 
     public  class  Connector{
 
         const  int  HEAD_SIZE = 4;
         private  TcpClient client;
         NetworkStream stream;
 
         public  bool  Connect( string  ip, int  port){
             try {
                 client =   new  TcpClient(ip,port);
                 stream = client.GetStream();
                 return  true ;
             }
             catch {
                 return  false ;
             }
         }
 
         public  void  Disconnect(){
             stream.Close();
             client.Close();
         }
 
         private  int  readType(){
             byte [] headData =  new  byte [HEAD_SIZE];
             stream.Read(headData,0,headData.Length);
 
             int  msgType = BitConverter.ToInt32(headData,0);
             return  msgType;
         }
 
         private  int  readSize(){
             byte [] headData =  new  byte [HEAD_SIZE];
             stream.Read(headData,0,headData.Length);
 
             int  msgSize = BitConverter.ToInt32(headData,0);
             return  msgSize;
         }
 
         private  byte [] readContent( int  leghth){
             byte [] content =  new  byte [leghth];
             stream.Read(content,0,content.Length);
             return  content;
         }
 
         public  Msg Read(){
             Msg msg =  new  Msg();
             msg.Type = readType();
             msg.Size = readSize();
 
             if  (msg.Size > 0) {
                 msg.Content = readContent(msg.Size);
             }
             return  msg;
         }
 
         public  void  Write( int  msgType, byte [] msgContent){
 
             byte [] msgTypeByte = BitConverter.GetBytes(msgType);
 
             int  msgSize = HEAD_SIZE+HEAD_SIZE+msgContent.Length;
             byte [] msgSizeByte = BitConverter.GetBytes(msgSize);
 
             int  totalSize = HEAD_SIZE+HEAD_SIZE+msgSize;
             byte [] msgByte =  new  byte [totalSize];
 
             int  index = 0;
             int  i = 0;
             for  (i=0;i<HEAD_SIZE;i++){  // put msg type
                 if  (msgTypeByte.Length>i){
                     msgByte[index] = msgTypeByte[i];
                 }
                 index++;
             }
 
 
             for  (i=0;i<HEAD_SIZE;i++){  // put msg size
                 if  (msgTypeByte.Length>i){
                     msgByte[index+i] = msgSizeByte[i];
                 }
                 index++;
             }
 
             for  (i=0;i<msgSize;i++){  // put msg content
                 if  (msgTypeByte.Length>i){
                     msgByte[index+i] = msgContent[i];
                 }
                 index++;
             }
 
             stream.Write(msgByte,0,msgByte.Length);
             stream.Flush();
         }
     }
}

 

主要用的是TcpClient,NetworkStream,BitConverter.

1
2
3
4
5
6
7
8
9
TcpClient client =  new  TcpClient(ip,port);  // 获取与服务器连接
NetworkStream stream = client.GetStream();  // 获取连接的流
stream.Read(buf,0,lenght);  // 读取至buf
stream.Write(buf,0,lenght);  // 写至buf
BitConverter.GetBytes(data);  // 用于将整数转为字节
BitConverter.ToInt32(data,0);  // 用于将字节转为整数
stream.Flush();  // 将流中缓存发出,而不等候
stream.Close();  // 关闭流
client.Close();  // 关闭连接

 

第三部分 protobuf-net

FQ下载安装:http://code.google.com/p/protobuf-net/

数据结构编译成dll:

先新建解决方案,新建库,添加下载的full/unity/dll。具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using  System;
using  ProtoBuf;
 
namespace  CSProtoData
{
     [ProtoContract]
     public  class  Head
     {
         [ProtoMember(1)]
         public  Int32 DataType {  get set ; }
         [ProtoMember(2)]
         public  Int64 DataDate {  get set ; }
         [ProtoMember(3)]
         public  byte [] DataContent {  get set ; }
     }
 
     [ProtoContract]
     public  class  Number
     {
         [ProtoMember(1)]
         public  Int32 Index {  get set ; }
         [ProtoMember(2)]
         public  Int64 Value {  get set ; }
     }
 
     public  class  Board
     {
         [ProtoMember(1)]
         public  Int64 Rank {  get set ; }
         [ProtoMember(2)]
         public  string  TargetName {  get set ; }
         [ProtoMember(3)]
         public  Int64 Number {  get set ; }
     }
 
     public  class  Request
     {
         [ProtoMember(1)]
         public  string  DataType {  get set ; }
         [ProtoMember(2)]
         public  Int64 DataDate {  get set ; }
         [ProtoMember(3)]
         public  Int32 Start {  get set ; }
         [ProtoMember(4)]
         public  Int32 End {  get set ; }
     }
}

编译完后,生成dll下面马上用到(同时也要拖放到unity/assets下)。

 

第三部分 下

因为protobuf-net的序列化和反序列化用的是jit,ios不支持jit,所以需采用编译成dll的方式来解决问题:

vs中,新建命令行程序,添加protobuf-net/full/unity/dll,添加刚生成的dll,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using  System;
using  ProtoBuf;
using  ProtoSerializer;
using  CSProtoData;
 
namespace  ProtoSerializer
{
     class  MainClass
     {
         public  static  void  Main( string [] args)
         {
             var  model = ProtoBuf.Meta.TypeModel.Create();
 
             model.Add( typeof (Head),  true );
             model.Add( typeof (Number),  true );
             model.Add( typeof (Board),  true );
             model.Add( typeof (Request),  true );
 
             model.Compile( "CSProtoSerializer" "CSProtoSerializer.dll" );
         }
     }
}

这里按运行后,会在目录下生成:CSProtoSerializer.dll,一样拖放到unity/assets下。

其中typeof()的,就是proto数据类型,在上半部分有定义的内容。

 

第四部分 unity代码

执行完以上步骤,unity/assets下应该有这么几个dll:

protobuf-net/full/unity/dll

proto的data的dll(第三部分)

data的序列化的dll(第三部分下,运行后生成的那个)

还有用于tcp连接的dll(第二部分)

那么实际在unity当中调用的代码则是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using  UnityEngine;
using  System.Collections;
using  TcpConnector;
using  ProtoBuf;
using  CSProtoData;
using  System.IO;
 
public  class  testTcp : MonoBehaviour {
 
     // Use this for initialization
     void  Start () {
         Connector conn =  new  Connector();
         bool  result = conn.Connect( "127.0.0.1" ,17093);
         Debug.Log(result);
 
         Head head= new  Head{};
         head.DataType = 2;
         head.DataDate = 201407312;
 
         MemoryStream memStream =  new  MemoryStream();
         ProtoBuf.Serializer.Serialize<CSProtoData.Head>(memStream, head);
         byte [] x = memStream.ToArray();
 
         conn.Write(1,x);
         conn.Write(1,x);
     }
     
     // Update is called once per frame
     void  Update () {
         
     }
}

 

新建个script,随便挂在比如camara的组件里即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值