博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity3D使用TCP/IP协议,传递protocol buffer消息protobuf-net
阅读量:6389 次
发布时间:2019-06-23

本文共 5648 字,大约阅读时间需要 18 分钟。

原文: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下载安装:

数据结构编译成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的组件里即可。

 

转载地址:http://jjsha.baihongyu.com/

你可能感兴趣的文章
Python笔记6(异常)-20160924
查看>>
纯数学教程 Page 203 例XLI (6)
查看>>
初识Git
查看>>
增强for循环对于“二维”数组进行循环的案例
查看>>
【百度地图API】百度API卫星图使用方法和卫星图对比工具
查看>>
oracle
查看>>
转 Hystrix入门指南 Introduction
查看>>
hihoCoder 网络流四·最小路径覆盖
查看>>
uva 1416 (SPFA) **月赛第E题的原题**
查看>>
vue案例 - vue-awesome-swiper实现h5滑动翻页效果
查看>>
JSP基础
查看>>
rabbitmq学习——交换机
查看>>
2018年4月26日笔记
查看>>
错误集合
查看>>
Linux-DNS服务器的配置与管理(上)
查看>>
rman理论(一)
查看>>
Mysql优化小结
查看>>
属性(Properties)和字段在C#中的关系
查看>>
C++ 文本查询2.0(逻辑查询)
查看>>
对另一个布局文件里的Button按钮进行监听
查看>>