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

protobuf-net - ing...

原文: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的组件里即可。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Node.js中,可以使用`net`模块来创建TCP服务器和客户端,同时也提供了对TCP/IP协议数据的解封装功能。 当服务器接收到TCP/IP协议的数据时,会触发`data`事件,通过监听该事件可以获取到接收到的原始二进制数据。接着可以通过Node.js内置的`Buffer`对象将二进制数据转换为字符串或者其他格式的数据。 下面是一个简单的示例代码,演示了如何解封装基于TCP/IP协议发过来的数据: ```javascript const net = require('net'); // 创建TCP服务器 const server = net.createServer((socket) => { console.log('客户端已连接'); // 监听数据接收事件 socket.on('data', (data) => { console.log('接收到数据:', data); // 解封装数据 const str = data.toString('utf8'); console.log('解封装后的数据:', str); }); // 监听连接断开事件 socket.on('end', () => { console.log('连接已断开'); }); }); // 启动服务器 server.listen(3000, () => { console.log('服务器已启动'); }); // 创建TCP客户端 const client = net.createConnection({ port: 3000 }, () => { console.log('已连接到服务器'); // 发送数据 client.write('Hello, world!'); }); // 监听数据接收事件 client.on('data', (data) => { console.log('接收到数据:', data); // 解封装数据 const str = data.toString('utf8'); console.log('解封装后的数据:', str); }); // 监听连接断开事件 client.on('end', () => { console.log('连接已断开'); }); ``` 在上面的示例中,服务器和客户端都监听了`data`事件,当接收到数据时会先输出原始的二进制数据,然后通过`toString()`方法将其转换为字符串格式的数据。这里使用了默认的编码方式`utf8`,也可以根据具体情况使用其他编码方式。 在实际应用中,可能需要根据协议规范对数据进行更复杂的解封装操作,这时可以使用第三方的解析库,比如`Protocol Buffers`等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值