客户端与服务器的沟通是网络游戏的根基。一个网络游戏,大部分业务需求都会涉及网络通信,而事实上在开发团队中,却只有少部分开发者真正处理过网络通信逻辑。因为网络通信逻辑总是被封装在框架的底层,处理业务的程序猿只需调用网络工程狮提供的接口即可达成所有的需求。而程序猿与工程狮的隔阂也由此拉开。
这篇文章将从实现Unity客户端网络通信功能出发,介绍网络通信的两种架构一一Socket与RPC。这里观点均来自我收集的网络资源整理,也有部分是我的个人感悟,不保证完全正确,欢迎讨论。
转载请说明出处。
文章的结构如下图所示,你可以根据自己的兴趣点选择阅读。
Socket的使用
关于线程Thread
socket百科
socket的设计理念及实现
NetworkView.rpc
UNet
RPC百科
RPC的设计理念及实现
socket与RPC的架构对比
Socket的使用
如前文所说,这篇文章将从实现Unity3D客户端的网络通信着手,这里将使用C#语言。
了解下面这些信息后,你即可实现基本的网络通信功能:
C#语言在System.Net.Sockets命名空间中提供了一个Socket类。
使用Socket.Connect(IPEndPoint endPoint)方法可与指定IP的远程主机建立连接。
使用Socket.Send(byte[] message)方法可发送字节消息。
使用Socket.Receive(byte[] message)方法可接受字节消息。
至此,一个客户端的简易网络通信功能就已经完成。
若想了解服务器端的处理,请参考:
C#socket通信 - 码农来了 - 博客园
https://www.cnblogs.com/sdyinfang/p/5519708.html
关于线程Thread
线程与网络通信没有直接关系,放在这篇文章中的主要目的是因为网络通信通常被放到单独的线程中,也是为了章节排版的对称。
了解下面这些信息后,你即可实现基本的多线程功能:
C#语言在System.Threading命名空间中提供了一个Thread类。
使用Thread.Start()方法即可开启一个新的线程。
那么,为什么网络通信功能通常都被放到单独的线程中呢?
原来这是因为,C#提供的socket架构的机制是同步的。就是说,线程执行到发送协议,将挂起,等待服务器端执行完毕,才开始执行下一行。
这样问题就变的很明显,产品的流畅度会被网速限制。
为了防止游戏在网速缓慢的情况下被影响而卡顿,大多数游戏项目的客户端选择了将网络通信功能放在单独的线程中,即,除了游戏的主线程之外,还会有一个发送协议的线程,和一个接受协议的线程。
但这样的做法也并非是一个强制选项。我猜测,市面上有些主流产品就是单线程。我猜测的依据在于,使用产品发送协议时,屏幕被锁死,出现网络加载图标,知道网络加载完成,才可以开始下一步操作。这是大概是因为,这些产品自身进行网络通信不比游戏那样频繁,且通信的内容对于下一步操作非常重要。
socket百科
阅读到这里,你已经会使用socket了。
可是,socket究竟是什么?
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。
若想了解更多,请参考:
socket(计算机专业术语)_百度百科
https://baike.baidu.com/item/socket/281150?fr=aladdin
socket的设计理念及实现
socket并不是一种协议,是在程序员层面上对TCP/IP协议的封装和应用。其实是一个调用接口,方便程序员使用TCP/IP协议栈而已。程序员通过socket来使用tcp/ip协议。但是socket并不是一定要使用tcp/ip协议,Socket编程接口在设计的时候,就希望也能适应其他的网络协议。
若想了解更多,请参考:
C# Socket网络编程精华篇 - 微冷的雨 - 博客园
http://www.cnblogs.com/weilengdeyu/archive/2013/03/08/2949101.html
Socket实现 - kakawater - 博客园
https://www.cnblogs.com/kakawater/p/7085122.html
NetworkView.rpc
依旧是从实现Unity3D客户端的网络通信着手,使用C#语言。
了解下面这些信息后,你即可实现基本的网络通信功能:
Unity游戏引擎提供了一个NetworkView组件。
使用Network.Connect可与指定IP的远程主机建立连接。
调用NetworkView.RPC方法即可调用到远程主机上的函数。
有[RPC]标签的函数才可被远程调用。
若想了解更多,请参考:
Unity - Scripting API: NetworkView.RPC
https://docs.unity3d.com/ScriptReference/NetworkView.RPC.html
UNet
也许你已经注意到Unity官方提供的API上关于NetworkView.rpc打上了这个提示"Method group is Obsolete"。Unity的版本更新迭代比较快,且版本差异比较大,经常修复重要BUG,或做框架调整。本来想好好研究下UNet,结果也看到一个提示"this API is experimental and might be changed or removed in the future."。
若想了解更多,请参考:
Unity - Scripting API: UNetUpdate
https://docs.unity3d.com/ScriptReference/Experimental.PlayerLoop.PreLateUpdate.UNetUpdate.html
RPC百科
不管Unity的版本如何迭代,可以看出它始终会提供一个RPC的架构,尽管使用的方法千变万化。
那么,RPC究竟是什么呢?
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
若想了解更多,请参考:
远程过程调用协议_百度百科
https://baike.baidu.com/item/%E8%BF%9C%E7%A8%8B%E8%BF%87%E7%A8%8B%E8%B0%83%E7%94%A8%E5%8D%8F%E8%AE%AE/6893245?fromtitle=RPC&fromid=609861&fr=aladdin
RPC的设计理念及实现
RPC 这个概念术语在上世纪 80 年代由 Bruce Jay Nelson 提出。这里我们追溯下当初开发 RPC 的原动机是什么?在 Nelson 的论文 "Implementing Remote Procedure Calls" 中他提到了几点:
简单:RPC 概念的语义十分清晰和简单,这样建立分布式计算就更容易。
高效:过程调用看起来十分简单而且高效。
通用:在单机计算中过程往往是不同算法部分间最重要的通信机制。
通俗一点说,就是一般程序员对于本地的过程调用很熟悉,那么我们把 RPC 作成和本地调用完全类似,那么就更容易被接受,使用起来毫无障碍。Nelson 的论文发表于 30 年前,其观点今天看来确实高瞻远瞩,今天我们使用的 RPC 框架基本就是按这个目标来实现的。
若想了解更多,请参考:
深入浅出 RPC - 浅出篇 - CSDN博客
https://blog.csdn.net/mindfloating/article/details/39473807
深入浅出 RPC - 深入篇 - CSDN博客
https://blog.csdn.net/mindfloating/article/details/39474123
RPC架构简单理解 - ChrisMurphy - 博客园
https://www.cnblogs.com/ChrisMurphy/p/6550184.html
socket与RPC的架构对比
socket作为“套接字”它传输的是远程数据;而RPC是在socket的基础上实现的,他传递的是远程过程(即函数方法)。
转载请说明出处
欢迎讨论!欢迎指正!
领取专属 10元无门槛券
私享最新 技术干货