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#与C++互操作实例讲解 什么是互操作? 在计算机科学领域,互操作意味着在不同编程语言或计算机系统之间交流和交换信息的能力。在本文中,我们将重点介绍如何使用C#和C++进行互操作。 为什么使用互操作? 尽管C#具有很高的开发速度和开发效率,但在一些实时应用程序或者特定场景下,使用C++能够提供更好的性能和一些功能。通过在C#和C++之间实现互操作,我们可以…

    C# 2023年5月14日
    00
  • C#中类与接口的区别讲解

    下面是”C#中类与接口的区别讲解”的完整攻略。 类和接口的定义 C#中的类是一种具有属性、方法和事件等成员的结构化数据类型,它描述了一个对象的特征和行为。而接口则是一种只定义方法签名的结构,不包含实现的成员,它定义了与类有关的一组方法、属性和事件的规范。 类的特点 类是一种实现,它可以被实例化。 类可以包含字段、属性、构造函数、方法等成员。 类支持继承,可以…

    C# 2023年6月7日
    00
  • C# 连接Access数据时总报找不到dbo.mdb的问题

    C#连接Access数据库时,有时会出现找不到dbo.mdb的问题,这一般是因为缺少连接字符串或者连接字符串格式不正确所引起的。下面详细讲解如何解决这一问题。 1. 确认连接字符串格式正确 在C#中连接Access数据时,一般需要使用到连接字符串。连接字符串是一个包含数据库连接信息的字符串,包括数据库类型、服务器地址、用户名、密码等信息。确认连接字符串格式正…

    C# 2023年5月31日
    00
  • C#通过接口与线程通信(捕获线程状态)示例代码

    C#通过接口与线程通信(捕获线程状态)示例的完整攻略如下: 线程状态概述 在进行线程通信之前,先要理解线程的状态。在 C# 中,线程有以下几种状态: Unstarted: 表示线程已被创建,但未开始执行。 Running: 表示线程正在运行。 Stopped: 表示线程已经停止。 WaitSleepJoin: 表示线程正在等待被调用,或正在进行 Wait、S…

    C# 2023年5月15日
    00
  • C#贪吃蛇游戏实现分析

    C#贪吃蛇游戏实现分析 简介 贪吃蛇是一种经典的游戏,它简单而有趣,很适合拿来练习编程的基础功底。这篇文章主要介绍如何用C#来实现一个贪吃蛇游戏。 实现思路 数据结构 贪吃蛇游戏中的核心数据结构是“蛇”。一条蛇由若干个“节点”组成,每个节点表示蛇身的一部分。为了表示一个蛇,我们可以使用一个“链表”来存储这些节点。 除此之外,还需要记录蛇的方向、蛇的长度以及食…

    C# 2023年6月6日
    00
  • C#之多余控件事件及代码删除问题

    标题:C#之多余控件事件及代码删除问题 正文: 在使用C#编写Windows应用程序时,我们有时会再设计界面时添加一些控件,后来又发现这些控件用处不大,或者我们修改了设计,需要删除这些控件,但却发现这些控件和它们绑定的事件和代码并没有完全删除。这就是所谓的多余控件事件及代码删除问题。 问题原因 造成多余控件事件及代码删除问题的原因主要有两个: 控件从设计器中…

    C# 2023年5月14日
    00
  • ASP.NET中HiddenField隐藏域控件的使用方法

    下面是ASP.NET中HiddenField隐藏域控件的使用方法攻略。 一、什么是HiddenField隐藏域控件 HiddenField隐藏域控件是ASP.NET Web表单中的一个服务器端控件,它会生成一个HTML隐藏域,可以用于在Web页面中存储一些不希望被用户看到的数据,比如一些服务器端的数据。 二、HiddenField隐藏域控件的使用方法 1. …

    C# 2023年6月3日
    00
  • C# Console.Read()方法: 从控制台读取一个字符

    Console.Read()是C#语言中的一个控制台读取方法,它从输入流中读取下一个字符,并将其作为整数返回。它的返回值是输入的字符对应的ASCII码值。如果读取到达到输入流的末尾,则返回-1。 在使用Console.Read()方法时,需要注意以下几点: 该方法只能读取一个字符,且输入缓冲区将保留任何其他字符或回车符。 如果用户输入了多个字符,则只返回第一…

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