【游戏技术群】959392658  【游戏出海群】12067810
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2422

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 918|回复: 33

[碧俐千仞] 设计Unity网络模块,该用异步还是多路复用?

[复制链接]  [移动端链接]
排名
19810
昨日变化
3

37

主题

216

帖子

834

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
38
蛮牛币
2616
威望
0
注册时间
2014-11-6
在线时间
179 小时
最后登录
2019-2-20

专栏作家

发表于 2019-1-15 00:05:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
开发Unity网络模块时,一般会有异步(多线程同理)、多路复用两种方法。它们分别是什么,以及孰优孰劣呢?

在《网络游戏实战(第2版)》的网络模块中,客户端使用了异步,服务端使用了多路复用。有读者问到为什么这么做,为什么不在客户端使用多路复用?这个问题很多人会遇到,决定写一篇文章说明这个问题。

先简单看看异步和多路复用是什么样子。

知乎@罗培羽

异步
异步程序的写法如下,会调用.net网络编程的API,使用BeginXXX和EndXXX这样的语法。实际上,程序内部会开启另外的线程去接收数据。


[AppleScript] 纯文本查看 复制代码
public class Echo : MonoBehaviour {



    Socket socket;



 //接收缓冲区

    byte[] readBuff = new byte[1024]; 



    public Start()

    {

 //Socket

        socket = new Socket(AddressFamily.InterNetwork,

            SocketType.Stream, ProtocolType.Tcp);

 //Connect

        socket.Connect("127.0.0.1", 8888);

        //BeginReceive

        socket.BeginReceive( readBuff, 0, 1024, 0, ReceiveCallback, socket);

    }



 //Receive回调

    public void ReceiveCallback(IAsyncResult ar){

        Socket socket = (Socket) ar.AsyncState;

        int count = socket.EndReceive(ar);

        string s = System.Text.Encoding.Default.GetString(readBuff, 0, count);

        socket.BeginReceive( readBuff, 0, 1024, 0,ReceiveCallback, socket);

    }

}



图示如下,调用BeginReceive后,程序就开启了一条新的线程,在新的线程里阻塞等待。等有消息回来时,才往下执行。
Unity网络编程异步和多路复用的应用场景1203.png


多路复用
异步程序写起来比较麻烦,而且代码量多,其实有一种更简便的处理方法,那就是使用poll或select。使用poll的代码如下。


[AppleScript] 纯文本查看 复制代码
//省略各种using

public class Echo : MonoBehaviour {



 //定义套接字

    Socket socket;



    public void Start()

    {

 //Socket

        socket = new Socket(AddressFamily.InterNetwork,

            SocketType.Stream, ProtocolType.Tcp);

 //Connect

        socket.Connect("127.0.0.1", 8888);

    }



    public void Update(){

        if(socket.Poll(0, SelectMode.SelectRead)){

            byte[] readBuff = new byte[1024];

            int count = socket.Receive(readBuff);

            string recvStr = 

                          System.Text.Encoding.Default.GetString(readBuff, 0, count);

        }

    }

}

无论如何,这段代码比异步要少一些。它的原理是使用socket.Poll,但socket有可读数据时,该方法返回true,如果没有返回false。那么程序只要在Update中不断去检测socket的状态,有数据的时候才去读取,也可以实现功能。

客户端为什么使用异步
我见过的大多数游戏程序使用异步或者多线程去处理网络模块。这就产生了个疑问,多路复用代码量少写起来更简单,但为什么不使用呢?在小型项目中其实使用哪种方式都没有太大区别,但当我们要考虑网络性能的时候,就要仔细斟酌,客户端不使用多路复用出于以下两个原因。

1.不断遍历

由上述程序可知,poll模式中,程序要在Update不断检测,可能每秒要检测30到60次,增加了计算量。而异步就没有这个问题,在网络消息到达的时候,线程被唤起,不需要遍历。

2.对主线程的影响

当接收到网络数据时,例子中使用了Encoding.Default.GetString把字节流转换成字符串,在实际游戏中,可能使用protobuf或者json协议,把字节流解析成协议对象有一定的计算量。在下图中,异步程序可以在异步线程中做解码,使得程序不会因为解码而卡住主线程。而Poll程序就做不到这一点,它在主线程中解码。Unity的脚本逻辑(Awake、Start、Update、碰撞、cpu渲染部分)都依赖于主线程,网络模块对主线程的影响越小,性能就越好。
Unity网络编程异步和多路复用的应用场景2478.png


服务端为什么使用多路复用
客户端和服务端多面临的情况不同,客户端一般只需要维持一个连接,而服务需要维持所有客户端的连接。多路复用为何取名叫“多路”,其核心就是要解决“多个连接”的问题。
Unity网络编程异步和多路复用的应用场景2574.png






因为服务端要处理各个玩家的逻辑,玩家之间可能还有交互,比如下图中,玩家1和玩家2都在一个房间内。
Unity网络编程异步和多路复用的应用场景2625.png


如果使用了多线程(异步),那么玩家1和玩家2的操作就有可能出现线程冲突,在处理逻辑时需要给房间对象加锁,《Unity3D网络游戏实战(第1版)》使用的就是这种方式。如果避开多线程,加锁的问题也就不复存在了,逻辑会更加明了,出Bug的可能性也会减少。多线程处理并不是一个简单的事情,需要很多经验积累才能处理好,《Unity3D网络游戏实战(第2版)》使用多路复用也就避开了这个问题。





最后依然还是放个广告,笔者近期出版的《Unity3D网络游戏实战(第2版)》详细介绍网络游戏的开发的全过程,比起第1版,更加注重网络编程的知识。看完本书,能够亲手从零开始制作一款有一定规模的网络游戏。
222752e6o60w5gzwt6qeds.png



回复

使用道具 举报

7日久生情
2110/5000
排名
1508
昨日变化
5

0

主题

671

帖子

2110

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
135463
好友
0
蛮牛币
264
威望
0
注册时间
2016-1-23
在线时间
599 小时
最后登录
2019-2-23
发表于 2019-1-15 07:24:09 | 显示全部楼层
666666666666777777777777

回复 支持 反对

使用道具 举报

0

主题

10

帖子

22

积分

Rank: 1

UID
202622
好友
0
蛮牛币
41
威望
0
注册时间
2017-1-17
在线时间
12 小时
最后登录
2019-1-24
发表于 2019-1-15 08:38:43 | 显示全部楼层
大概懂了你的意思,最近我也在看这本书,讲的很详细。面对初学者,避免多线程是好点,但是实际开发中服务器多线程还是比较常见的吧?毕竟可能发生堵塞。

回复 支持 反对

使用道具 举报

排名
472
昨日变化
1

236

主题

1万

帖子

2万

积分

Rank: 12Rank: 12Rank: 12

UID
78862
好友
17
蛮牛币
33890
威望
0
注册时间
2015-3-11
在线时间
3139 小时
最后登录
2019-2-22
QQ
发表于 2019-1-15 09:17:26 | 显示全部楼层
书很不错,

回复

使用道具 举报

6蛮牛粉丝
1051/1500
排名
3818
昨日变化
1

5

主题

432

帖子

1051

积分

Rank: 6Rank: 6Rank: 6

UID
269155
好友
2
蛮牛币
1958
威望
0
注册时间
2018-2-22
在线时间
224 小时
最后登录
2019-2-22
发表于 2019-1-15 09:32:17 | 显示全部楼层
谢谢分享

回复

使用道具 举报

3偶尔光临
262/300
排名
14363
昨日变化
1

2

主题

168

帖子

262

积分

Rank: 3Rank: 3Rank: 3

UID
310426
好友
0
蛮牛币
546
威望
0
注册时间
2019-1-2
在线时间
34 小时
最后登录
2019-2-22
发表于 2019-1-15 09:54:39 | 显示全部楼层
想买本看看
[发帖际遇]: ApolloAR 在论坛发帖时没有注意,被小偷偷去了 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
2838/5000
排名
747
昨日变化
2

24

主题

454

帖子

2838

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
123323
好友
25
蛮牛币
11844
威望
0
注册时间
2015-9-21
在线时间
980 小时
最后登录
2019-2-22

认证开发者活力之星

发表于 2019-1-15 09:54:43 | 显示全部楼层
第二版的书已经出版了吗?? 等了好久了!!! 如果出版了 请发一下购买链接。

回复 支持 反对

使用道具 举报

5熟悉之中
577/1000
排名
4794
昨日变化
23

0

主题

67

帖子

577

积分

Rank: 5Rank: 5

UID
255447
好友
2
蛮牛币
1271
威望
0
注册时间
2017-11-21
在线时间
204 小时
最后登录
2019-2-23
发表于 2019-1-15 10:15:45 | 显示全部楼层
讲解的换可以

回复

使用道具 举报

7日久生情
3312/5000
排名
250
昨日变化

7

主题

366

帖子

3312

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
195
好友
4
蛮牛币
4211
威望
0
注册时间
2013-6-4
在线时间
937 小时
最后登录
2019-2-12
发表于 2019-1-15 10:27:39 | 显示全部楼层
lixiaobai 发表于 2019-1-15 09:54
第二版的书已经出版了吗?? 等了好久了!!! 如果出版了 请发一下购买链接。 ...

对啊,第二版出了没有啊,第一版的买了看完了
[发帖际遇]: baobaoxiaoxuan 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
677/1000
排名
4285
昨日变化
26

1

主题

211

帖子

677

积分

Rank: 5Rank: 5

UID
245227
好友
0
蛮牛币
890
威望
0
注册时间
2017-9-21
在线时间
127 小时
最后登录
2019-2-20
发表于 2019-1-15 11:56:31 | 显示全部楼层
666666666666666666

回复 支持 反对

使用道具 举报

排名
168
昨日变化

9

主题

419

帖子

3916

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
7264
好友
1
蛮牛币
16569
威望
0
注册时间
2013-11-6
在线时间
1210 小时
最后登录
2019-2-23

VIP社区QQ达人活力之星

QQ
发表于 2019-1-15 17:04:46 | 显示全部楼层
66666667

回复

使用道具 举报

排名
19810
昨日变化
3

37

主题

216

帖子

834

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
38
蛮牛币
2616
威望
0
注册时间
2014-11-6
在线时间
179 小时
最后登录
2019-2-20

专栏作家

 楼主| 发表于 2019-1-15 21:54:41 | 显示全部楼层
Cckid 发表于 2019-1-15 08:38
大概懂了你的意思,最近我也在看这本书,讲的很详细。面对初学者,避免多线程是好点,但是实际开发中服务器 ...

对于服务端来说,实际项目也是尽量在逻辑层避免多线程的,可能会在底层做各种封装,但对于编写逻辑,要做到透明。举个例子说AB两个玩家在房间里战斗,如果A和B由不同的线程处理,那线程间的交互就会很多。如果整个房间的玩家都由一个线程去处理,那就会大大减少了。 不少游戏用的是单线程+多进程的结构,大部分逻辑可以做到不用线程/进程的交互。

回复 支持 反对

使用道具 举报

排名
19810
昨日变化
3

37

主题

216

帖子

834

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
38
蛮牛币
2616
威望
0
注册时间
2014-11-6
在线时间
179 小时
最后登录
2019-2-20

专栏作家

 楼主| 发表于 2019-1-15 21:55:54 | 显示全部楼层

谢谢好评~ 那就多多推广给你们的同事/同学吧

回复 支持 反对

使用道具 举报

排名
19810
昨日变化
3

37

主题

216

帖子

834

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
38
蛮牛币
2616
威望
0
注册时间
2014-11-6
在线时间
179 小时
最后登录
2019-2-20

专栏作家

 楼主| 发表于 2019-1-15 21:56:56 | 显示全部楼层

欢迎指点,然后提出有疑惑的或者不正确的地方,还会继续修正的

回复 支持 反对

使用道具 举报

排名
19810
昨日变化
3

37

主题

216

帖子

834

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
38
蛮牛币
2616
威望
0
注册时间
2014-11-6
在线时间
179 小时
最后登录
2019-2-20

专栏作家

 楼主| 发表于 2019-1-15 21:57:53 | 显示全部楼层
lixiaobai 发表于 2019-1-15 09:54
第二版的书已经出版了吗?? 等了好久了!!! 如果出版了 请发一下购买链接。 ...

终于出了,我也等了好久。京东、亚马逊、新华书店、当当、淘宝等等主流渠道都有哦

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表