找回密码
 注册帐号

扫一扫,访问微社区

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

34
回复
1413
查看
[ 复制链接 ]
排名
19946
昨日变化

38

主题

219

帖子

850

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
39
蛮牛币
2626
威望
0
注册时间
2014-11-6
在线时间
189 小时
最后登录
2019-4-24

专栏作家

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日久生情
2233/5000
排名
1394
昨日变化

0

主题

693

帖子

2233

积分

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

UID
135463
好友
0
蛮牛币
173
威望
0
注册时间
2016-1-23
在线时间
650 小时
最后登录
2019-4-24
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 显示全部楼层
大概懂了你的意思,最近我也在看这本书,讲的很详细。面对初学者,避免多线程是好点,但是实际开发中服务器多线程还是比较常见的吧?毕竟可能发生堵塞。
回复 支持 反对

使用道具 举报

9以坛为家
20350/50000
排名
463
昨日变化

236

主题

1万

帖子

2万

积分

Rank: 9Rank: 9Rank: 9

UID
78862
好友
17
蛮牛币
37987
威望
0
注册时间
2015-3-11
在线时间
3248 小时
最后登录
2019-4-24
QQ
2019-1-15 09:17:26 显示全部楼层
书很不错,
回复

使用道具 举报

6蛮牛粉丝
1147/1500
排名
3616
昨日变化

5

主题

472

帖子

1147

积分

Rank: 6Rank: 6Rank: 6

UID
269155
好友
2
蛮牛币
2329
威望
0
注册时间
2018-2-22
在线时间
256 小时
最后登录
2019-4-24
2019-1-15 09:32:17 显示全部楼层
谢谢分享
回复

使用道具 举报

5熟悉之中
602/1000
排名
10816
昨日变化

2

主题

406

帖子

602

积分

Rank: 5Rank: 5

UID
310426
好友
0
蛮牛币
482
威望
0
注册时间
2019-1-2
在线时间
98 小时
最后登录
2019-4-24
2019-1-15 09:54:39 显示全部楼层
想买本看看
回复

使用道具 举报

7日久生情
2909/5000
排名
724
昨日变化

24

主题

460

帖子

2909

积分

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

UID
123323
好友
25
蛮牛币
12030
威望
0
注册时间
2015-9-21
在线时间
1021 小时
最后登录
2019-4-24

认证开发者活力之星一掷千金

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

使用道具 举报

5熟悉之中
660/1000
排名
4268
昨日变化

0

主题

68

帖子

660

积分

Rank: 5Rank: 5

UID
255447
好友
2
蛮牛币
1489
威望
0
注册时间
2017-11-21
在线时间
248 小时
最后登录
2019-4-1
2019-1-15 10:15:45 显示全部楼层
讲解的换可以
回复

使用道具 举报

7日久生情
3319/5000
排名
251
昨日变化

7

主题

366

帖子

3319

积分

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

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

对啊,第二版出了没有啊,第一版的买了看完了
回复 支持 反对

使用道具 举报

5熟悉之中
744/1000
排名
4111
昨日变化

1

主题

234

帖子

744

积分

Rank: 5Rank: 5

UID
245227
好友
0
蛮牛币
959
威望
0
注册时间
2017-9-21
在线时间
149 小时
最后登录
2019-4-24
2019-1-15 11:56:31 显示全部楼层
666666666666666666
回复 支持 反对

使用道具 举报

排名
163
昨日变化

9

主题

421

帖子

3971

积分

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

UID
7264
好友
1
蛮牛币
16820
威望
0
注册时间
2013-11-6
在线时间
1233 小时
最后登录
2019-4-24

VIP活力之星

QQ
2019-1-15 17:04:46 显示全部楼层
66666667
回复

使用道具 举报

排名
19946
昨日变化

38

主题

219

帖子

850

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
39
蛮牛币
2626
威望
0
注册时间
2014-11-6
在线时间
189 小时
最后登录
2019-4-24

专栏作家

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

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

使用道具 举报

排名
19946
昨日变化

38

主题

219

帖子

850

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
39
蛮牛币
2626
威望
0
注册时间
2014-11-6
在线时间
189 小时
最后登录
2019-4-24

专栏作家

楼主 2019-1-15 21:55:54 显示全部楼层

谢谢好评~ 那就多多推广给你们的同事/同学吧
回复 支持 反对

使用道具 举报

排名
19946
昨日变化

38

主题

219

帖子

850

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
39
蛮牛币
2626
威望
0
注册时间
2014-11-6
在线时间
189 小时
最后登录
2019-4-24

专栏作家

楼主 2019-1-15 21:56:56 显示全部楼层

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

使用道具 举报

排名
19946
昨日变化

38

主题

219

帖子

850

积分

Rank: 9Rank: 9Rank: 9

UID
53741
好友
39
蛮牛币
2626
威望
0
注册时间
2014-11-6
在线时间
189 小时
最后登录
2019-4-24

专栏作家

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

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

使用道具 举报

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

本版积分规则