C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信

C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信

简介

Protocol Buffer(又称protobuf)是Google开发的一种数据序列化格式,它比XML和JSON更快、更小、更简单。由于最初是用于Google内部的系统和数据通信,并且其生成和解析代码性能优秀,因此被开源出来,可供广泛的应用使用。

Unity 的网络通信有多种方式,传统的网络通信方式使用的是二进制通信,Protocol Buffer 序列化后的数据包十分小巧,带来了传输效率的很大提升。本文介绍了如何使用 C# 库在 Unity 中进行 Protocol Buffer 序列化及网络通信。

使用ProtoBuf进行数据序列化

首先,需要引入 protobuf 的库文件,可以通过NuGet等工具来安装Protobuf-net,它是一个比较普及的C#的protobuf序列化库,有很好的公共库支持,适合Unity项目使用。

打开 Visual Studio 或者 Visual Studio Code 在项目的引用中添加 protobuf 库

using ProtoBuf;
using System;
[ProtoContract]
public class UserInfo
{
    [ProtoMember(1)]
    public int Id { get; set; }

    [ProtoMember(2)]
    public string Name { get; set; }
}

上述代码中,我们定义了一个名为 UserInfo 的类,加上 ProtoContract 标签,这是 protobuf 序列化的必要标记。同时,类中的属性也需要使用 ProtoMember 标签标注一下,用来指定属性序列化后的标记数字。

当类规模非常大的时候,我们可以通过 ProtoInclude 标签将已有的消息类型引入到消息基类中,从而减少代码量和工作量。

[ProtoContract]
[ProtoInclude(1, typeof(UserInfo))]
public abstract class BaseMessage
{

}

使用ProtoBuf进行网络通信

在 Unity 中实现 Socket 通信无外乎两个关键步骤:客户端向服务端发送消息、服务端收到消息并进行处理并向客户端回复消息。

客户端向服务端发送消息

客户端向服务端发送消息时,需使用 Socket 建立连接,然后将请求数据序列化后发送到服务端。

public class Client : MonoBehaviour
{
    void Start()
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));

        UserInfo userInfo = new UserInfo { Id = 1, Name = "Debra" };
        byte[] buffer;
        using (MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize(ms, userInfo);
            buffer = ms.ToArray();
        }

        socket.Send(buffer);
    }
}

在上面的代码中,我们首先使用 Socket.Connect() 方法将客户端连接到指定的 IP 和端口上,接着我们创建一个 UserInfo 实例,在下一步中将其序列化成我们期望的二进制格式,最后使用 Socket.Send() 方法将请求数据发送到服务端。

服务端收到消息并进行处理并向客户端回复消息

当服务端接收到客户端的请求消息后,服务端需要先解析该请求消息,~~处理逻辑~~ ,制作响应消息并将响应消息序列化后返回给客户端。

public class Server : MonoBehaviour
{
    void Start()
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));
        socket.Listen(0);
        Socket clientSocket = socket.Accept();

        byte[] buffer = new byte[1024];
        int length = clientSocket.Receive(buffer);
        byte[] data = new byte[length];
        Array.Copy(buffer, data, length);

        UserInfo userInfo = null;
        using (MemoryStream ms = new MemoryStream(data))
        {
            userInfo = Serializer.Deserialize<UserInfo>(ms);
        }

        //处理逻辑
        userInfo.Name = userInfo.Name + "hello";

        byte[] sendBuffer;
        using (MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize(ms, userInfo);
            sendBuffer = ms.ToArray();
        }

        clientSocket.Send(sendBuffer);
        clientSocket.Close();
    }
}

在上述代码中,首先我们创建一个 Socket 执行 listen 监听,当客户端连接后,则会产生一个新的客户端socket。接着,我们使用客户端socket的 Receive() 方法来接收客户端发来的请求,同样需要将接收到的数据进行反序列化,接下来进行我们期望的业务逻辑处理来生成响应(在这个例子中,只是在UserName 末尾添加了“hello”的字样表示已经处理好了响应)。最后将这个响应数据通过 Socket.Send() 发送给客户端。

示例说明

在示例代码中,我们首先创建了一个 UserInfo 类作为 protobuf 的序列化格式,之后定义了一个 Server 和一个 Client 来表示服务端和客户端。在具体的执行中,服务端首先使用 Socket.Bind() 方法将服务器绑定到指定的端口,接着使用 Socket.Listen() 来启动监听。当客户端连接到服务端时,服务端则会调用 Socket.Accept() 方法并返回一个新的客户端Socket,之后通过该客户端 Socket 来接收客户端发来的请求。服务端处理完逻辑后,将响应数据序列化,并通过客户端Socket.Send() 将响应数据回传给客户端。 客户端则负责将请求数据序列化,并调用 Socket.Send() 方法向服务端发送请求数据。

总结

使用 protobuf 序列化技术来进行网络通信是一种非常良好的解决方案,它克服了二进制数据格式和传送速度之间的矛盾。在Unity中使用protobuf,不仅可以提高我们代码的执行效率,还可以提升我们的通信性能和体验。在实际项目中,借助 protobuf 进行数据序列化来进行通信,不仅可以进行各种尝试和创新,还有助于保障网络通信的质量、稳定性和安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • C#微信开发之微信公众号标签管理功能

    C#微信开发之微信公众号标签管理功能攻略 简介 本文将为读者介绍如何在C#中使用微信开发工具包开发微信公众号中标签管理功能。标签管理功能可用于公众号中对粉丝进行标记或分类,方便后续进行针对性推送。 前置条件 在开始开发之前,开发者需要准备以下内容: 在微信公众平台中创建一个公众号,并获取该公众号的AppId和AppSecret; 在Visual Studio…

    C# 2023年5月31日
    00
  • ASP.NET中ListView(列表视图)的使用前台绑定附源码

    下面我将为您讲解如何在ASP.NET中使用ListView控件进行列表视图的展示,以及如何在前台绑定数据和附源码。 一、什么是ListView控件 ListView控件是ASP.NET Web应用程序中用于呈现数据列表的一种控件,它可以使用模板来定制呈现方式,提供了更丰富的数据呈现方式,比如表格、列表、瓷砖等。 二、ListView控件的使用方法 1. 新建…

    C# 2023年6月3日
    00
  • LINQ操作符SelectMany的用法

    下面是对” LINQ操作符SelectMany的用法 “的详细解释和示例说明。 什么是 SelectMany? 先来了解一下 SelectMany。在 LINQ 中,SelectMany 多用于关联查询,用于扁平化嵌套集合。SelectMany 可以将一个序列中的每个元素转换为另一个序列,并将每个序列的元素组合成一个序列。这一操作通常用于关联查询,将子类转换…

    C# 2023年6月1日
    00
  • .Net下的签名与混淆图文分析

    我来为大家详细讲解“.Net下的签名与混淆图文分析”的完整攻略,包含以下内容: 什么是.Net下的签名与混淆 在 .Net 程序中,签名是指通过一定的算法对程序集中的每个方法、属性或成员类型等进行计算而得出的一段字节码。而混淆是指在保留程序功能不变的情况下,修改程序代码的结构和算法,使得程序难以被反编译或者逆向工程分析。 如何使用签名来保证程序编译的正确性 …

    C# 2023年5月31日
    00
  • c#动态编译执行对象方法示例 运用映射机制创建对象

    首先我们来详细讲解一下如何在C#中动态编译执行对象方法,具体步骤包括以下几个方面: 1.使用C#动态编译器进行编译2.使用反射获取程序集,类型以及方法3.创建对象实例并执行方法 步骤1:使用C#动态编译器进行编译 使用C#动态编译器可以将代码字符串编译成程序集,代码示例如下: string code = @"using System; public…

    C# 2023年6月1日
    00
  • C# FileAttributes.Archive:表示文件为归档文件

    FileAttributes.Archive方法的作用与使用方法 作用 在C#语言中,FileAttributes.Archive方法是用来获取或设置文件(或文件夹)的归档属性的。在计算机领域中,归档属性通常被用于标识哪些文件需要备份或复制,或者已经被备份或复制过。当我们修改或者创建一个文件时,系统会自动将该文件的归档属性置为“归档”(Archive)。也就…

    C# 2023年4月19日
    00
  • relaxlife.net发布一个自己开发的中文分词程序

    下面我将为你详细讲解“relaxlife.net发布一个自己开发的中文分词程序”的完整攻略。 准备工作 首先,我们需要准备好以下工具和环境:- Python 3及以上版本;- 第三方中文分词库(如jieba);- Flask框架;- HTML、CSS、JavaScript基础知识。 开发过程 步骤一:安装第三方分词库 打开命令行终端,使用以下命令安装jieb…

    C# 2023年5月31日
    00
  • extjs DataReader、JsonReader、XmlReader的构造方法

    ExtJS提供了三种数据读取器(DataReader):JsonReader、XmlReader、ArrayReader。其中JsonReader与XmlReader是最常用的两种,它们可以将Json和Xml数据解析成ExtJS中的数据集合(store). DataReader是一种工具,用于将来自服务器的响应数据解析成更易于在ExtJS中使用的格式。各个类…

    C# 2023年6月1日
    00
合作推广
合作推广
分享本页
返回顶部