Unity C# Scoke 如何实现网络通讯

2024-08-22 14:48

本文主要是介绍Unity C# Scoke 如何实现网络通讯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

强联网在我们的游戏开发中所占比重越来越大,尤其是开发MMO游戏时,更需要强联网来进行实时更新,所以我们就有了强联网的需要。

首先我们得清楚强联网的工作原理,说到强联网,我们就必须说到socket。

socket是对tcp/ip协议的封装和应用,是面向程序员的,给我们提供了操作网络的接口,但是我们也必须基本了解其工作原理:

强联网我们主要使用的是TCP和UDP,首先我们说一下TCP。

一说到TCP,必然会想到三次握手和四次挥手,建立连接和断开连接的原理虽然在编程过程中不会涉及太多,但还是有了解的必要。

三次握手:客户端和服务端建立连接需要三次握手

    第一次:客户端向服务端发送报文,向服务器发送连接请求;

    第二次:服务端向客户端返回ACK报文,通知客户端可以连接;

    第三次:客户端收到服务端报文,正式连接服务端。

三次握手完成。

四次挥手:客户端要与服务器断开连接,需要四次挥手

    第一次:客户端向服务端发送FIN报文,向服务器发送中断连接请求;

    第二次:服务器收到客户端中断请求,向服务器发送已得知中断请求,但服务器还有资源未处理,需要等待;

    第三次:服务器处理完数据后,再次向客户端发送报文,告诉客户端可以断开连接了;

    第四次:客户端收到服务端断开连接的确认信息后,最后发送信息看是否真的断开连接了,如果服务器没有一段时间没有回应,则说明已经断开,中断过程完成;

四次挥手完成。

那么我们如何使用强联网呢?

在c#中我们可以通过使用Socket来进行连接:

在服务端的流程:

    创建Socket->绑定IP端口->设置排队连接请求数量->启动监听->收发消息->关闭

在客户端的流程:

    创建Socket->连接对应IP端口->开始收发->关闭

我们会发现,服务端的流程比客户端长,那是因为客户端只需要连接一个服务器就好了,而服务端要接收不同的客户端。

具体Socket接口的使用在网上都有教程,在这里不做多述,只需要注意一点就是选择TCP,UDP使用不同的参数:

serverSocket =new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

这个是TCP的连接,三个参数分别是地址簇(ipv4),传输模式(流模式),协议(TCP)

而如果我们要UDP连接,则要如下:

serverSocket =new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);

UDP所需要的传输模式是数据报模式,所以我们在改变协议的同时,也要记得改变传输类型。

接下来就进入了我们的正题,有一定开发经验的游戏开发者一定知道,在网络传输数据的过程中会出现分包粘包的现象,我们首先来说一下什么叫分包、粘包。

    分包:传输数据不完整,一条信息被分成多次发送。

比如我们发送了一条信息:“你好”,如果分包现象发生,我们可能只收到了“你”,却没有收到“好”,这样就会导致数据的不完整。

    粘包:传输的多条数据粘在一起,比如我发了两句话“你好”和“我是小李”,我们可能会收到“你好我是小李”,也可能收到“你好我是”“你好我”“你好我是小”,后几种情况是分包粘包同时发生,我们肯定不期望这种现象发生,所以我们就有必要对我们发送的数据进行编辑。

解决方案: 我们每发送的一条数据就是一个数据包,我们是通过使用字节流来传输数据的,所以当我们每发送一个数据包,就顺便附带上数据包的长度,这样就形成了“数据包头”+“包体”的结构,包头用来存储数据包长度,包体用来存储具体的数据,每当我们接受数据时,首先读取数据包头,得到数据长度,再和已经传过来的长度对比,如果长度足够,说明至少传过来一个完整的包,我们就可以根据长度来取包体,如果不够,我们先不读取,直到长度满足时,我们再把这条数据进行读取。

这样就能方便的解决分包粘包的问题,但是我们之前接受到的不完整的信息放到哪呢?我们就需要一个缓存区,如果数据不完整,我们先放在缓存,当数据完整时,再取出读取。这里有一种建立缓存区的方案,通过内存流来读取。

    缓存区:我们使用内存流MemoryStream来进行读写操作,如果我们收到数据,我们就将数据写入内存流,当内存流的长度满足包头长度时,就将消息取出读取,流的操作比较基本,可以查阅资料了解,这里只提供一条思路。

    既然说到了数据包,那我们接着把数据包说完,数据包头+包体是我们最基本的结构,但我们的数据不可能就这样来传输,因为一旦有人截获我们的数据,就能轻易的修改我们的数据值,对游戏造成影响,所以我们必须要对数据包进行加密。

     一般情况下,我们会使用CRC进行冗余验证,看数据包是否传输完整,然后自定义自己的加密方式,将数据包加密以后再发出,有的项目还会对数据包进行压缩,所以我们这里给出一种通用的结构:数据头(长度)+冗余验证(CRC)+是否压缩+包体(加密后)。

这样,我们就可以对包进行加密操作以及完整性验证,保证我们的数据正确性、保密性和完整性。

    接下来就是传输协议,我们传输的数据都是字节流,那么我们收到这些字节流后如何处理呢?这就需要我们对数据包进行进一步编辑,给数据包一个协议ID,即把包体分为两部分:包体=协议ID+内容;当我们收到数据后,首先进行拆包,获取到协议ID后,就进行对应ID的事件派发,这里我们会用到观察者模式,下节会说到;我们派发事件后,对应的功能就会被执行,并且返回新的数据发送到另一端。那么我们通常都会有那些协议呢?

    通常我们在Socket中,最不能缺少的协议就是心跳,心跳是检验客户端和服务器是否连接、是否断线的非常有效的方法。服务器会每隔一段时间给客户端发送一个心跳包,如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没 有收到服务器的心跳包,则认为连接不可用。

    除了心跳包,我们还会定义一些通用的包,如邮件、聊天等,具体要根据我们的需要来制定,比如我们要做一个MMORPG游戏,那么我们就有必要定义关于玩家位置、行为等相关的协议。

    具体协议的实现,我们通常会用到类来接收包的数据,通常会有一个基类包,所有的协议类都继承这个基类,但如果数据的复杂度不是很大的话,我们可以使用结构体,将原来的基类改为使用接口,这也是一种不错的优化网络模块的方式。

    总之,我们在游戏开发中通常使用弱联网进行登录验证,强联网用于游戏内部,所以Socket的使用在游戏开发中所占比例以及重要程度不言而喻,这也是我们不断研究、不断探索、不断优化的原因。下一节我们就具体讲一讲观察者模式以及在网络模块中的应用。

这篇关于Unity C# Scoke 如何实现网络通讯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096575

相关文章

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录