目录

可靠的UDP协议

这一章节中,我们会介绍引擎中支持的可靠的UDP协议(RUDP)!

前言:

我们知道,CBE引擎是支持TCP协议的,并且在许多网络应用中,为了可靠性都是采用TCP协议。那为什么我们引擎还要去支持RUDP协议呢?我们先来了解几个概念。


TCP

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

其中最核心的就是其可靠性,主要表现在:

1、数据包顺序保障
2、超时重传
3、丢包重发
4、流量控制

具体请参见WIKI百科:《Transmission Control Protocol》一文。

既然TCP协议有这么多优势,为什么还需要RUDP协议以及RUDP协议是什么呢?


什么是可靠的UDP协议(RUDP)?

我们先来看看传统的UDP协议是什么?

UDP

UDP(User Datagram Protocol)用户数据报协议,它与TCP协议一样用于处理数据包,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。可靠性由上层应用实现,所以要实现UDP的可靠性传输,必须通过应用层来实现和控制。而我们引擎支持的RUDP协议就是基于UDP同时实现了可靠性的一种协议。UDP的详细介绍请参见WIKI百科:《User Datagram Protocol》一文。


引擎支持的RUDP协议

RUDP(Reliable UDP)是可靠的用户数据报协议。它旨在提供一种解决方案,比UDP可靠,比TCP开销小。其中UDP为了低时延、低带宽占用等特性,无法保证是否丢包、顺序是否一致,而TCP增加了太多复杂度和开销来达到可靠性。为了RUDP获得更高的服务质量,它扩展了UDP,并实现了类似于TCP的功能,且开销更小。


应用场景的选择

说了这么多,那对于CBE引擎开发者,在TCP和RUDP之间如何进行选择呢?

选择使用哪种类型的套接字协议,完全取决于开发者编写的应用类型。如MMO游戏,那么对于状态同步的准确性、顺序等有一定要求,一般采用TCP或RUDP。再比如类似直播音视频的应用,业务本身的数据是可以允许缺失的,同时其成本和时延要求比较高,那采用UDP或RUDP是个不错的选择。

总结如下:

应用类型 RUDP TCP
实时性要求敏感(如FPS) 优选 X
带宽占用敏感(成本考虑) X 优选

Tips:

带宽占用上,RUDP比TCP大? 由于RUDP为了可靠性的保障以及根据应用需要而配置的高实时参数的情况下,流量会耗费更多。


如何在引擎应用中使用RUDP协议

在ComblockEngine中已经内置了RUDP协议的支持,为了使开发者对协议的选择更加自由简单,对相应的配置进行了简化并在客户端SDK上提供了配置入口。接下来我们来看看具体如何在引擎中使用RUDP协议。


1、客户端上使用RUDP进行连接

只需在合适的应用场景下,从客户端上进行选择和配置即可。

引擎所有支持的客户端SDK插件上,都对RUDP做了开关设置,且默认的都是开启使用的状态。同时,针对RUDP的特性,添加了BUFFER_MAX的设置。

一旦RUDP是打开状态,则在与LoginApp完成账户认证后,客户端会使用RUDP的方式与BaseApp进行连接,完成RUDP的通讯。

下面我们按照不同客户端进行阐述:

1.1、Unity3D

我们知道,Unity3D中,SDK插件的入口是clientapp脚本。如下图:

从图中红色框可以看到:

1、Force Disable UDP:是否强制关闭UDP功能,默认是不勾选状态,即开启RUDP。

2、UDP_SEND_BUFFER_MAX:设置UDP发送的缓冲区大小。

3、UDP_RECV_BUFFER_MAX:设置UDP接收的缓冲区大小。

开发者可视自己的应用场景的不同而对这三个参数进行不同的调整,就可完美、自由的控制RUDP协议!非常容易吧!


2、引擎端上可选的配置选项

服务端为了更好的控制RUDP协议,也相应增加了一些配置选项。

Tips:

项目的引擎端配置请在{项目资产库}/res/server/kbengine.xml下进行修改,如该文件中不存在的字段,请自行根据格式添加。

2.1、reliableUDP字段

channelCommon字段中新增了reliableUDP字段,该字段中对RUDP进行了各个方面的配置。如下:

<reliableUDP>
    <!-- Equivalent to TCP RCV_BUF, unit is the number of UDP-packages -->
    <readPacketsQueueSize>
        <internal>				1024		</internal>
        <external>				128			</external>
    </readPacketsQueueSize>

    <!-- Equivalent to TCP SND_BU, unit is the number of UDP-packages -->
    <writePacketsQueueSize>
        <internal>				1024		</internal>
        <external>				128			</external>
    </writePacketsQueueSize>

    <!-- internal update timer interval in millisec, 0 is default(100millisec)  -->
    <tickInterval>				10			</tickInterval>
    <!-- Retransmission TimeOut(millisec)  -->
    <minRTO>					10			</minRTO>
    <!-- ACK skipping times, 0 is default  -->
    <missAcksResend>			2			</missAcksResend>
    
    <!-- change MTU size, 0 is default(1400) -->
    <mtu>						0			</mtu>

    <!-- false: disable congestion control -->
    <congestionControl>			false		</congestionControl>
    <nodelay>					true		</nodelay>
</reliableUDP>

其中:

readPacketsQueueSize int, 接收的缓冲区队列大小,单位是包的数量。该参数类似于TCP协议中的接收缓冲区大小。其中internal针对内部的RUDP协议,external则针对外部的提供给客户端的RUDP协议。

writePacketsQueueSize int,类似的,发送的缓冲区队列大小。

tickInterval int,内部的更新间隔,单位毫秒。默认值为0,表示100毫秒。

minRTO int,最小的重传超时时间,单位毫秒。当超过该时间时,认为需要重传。

missAcksResend int,当前跳过的或丢失的ACK数量超过该值时,认为需要重新发送。默认为0,表示不重新发送。

mtu int,最大传输单元,指所能通过的最大数据包大小,单位为字节。默认值为0,表示1400字节。

congestionControl bool,是否开启拥塞控制。false表示不开启拥塞控制。

nodelay bool,是否开启延迟。true表示不开启延迟。该参数类似于TCP协议中的NODELAY设置,具体请参考TCP-Forcing data delivery


2.2、externalUdpPorts

针对有外部访问需求的App,如BaseApp、LoginApp,在原有的TCP端口设置上,都增加了UDP端口设置字段。如下方的BaseApp配置块:

<baseapp>
    <!-- 脚本入口模块, 相当于main函数 
        (Entry module, like the main-function)
    -->
    <entryScriptFile> kbemain </entryScriptFile>

    <!-- 指定接口地址,可配置网卡名、MAC、IP
        (Interface address specified, configurable NIC/MAC/IP) 
    -->
    <internalInterface>  </internalInterface>
    <externalInterface>  </externalInterface>						<!-- Type: String -->
    
    <!-- 强制指定外部IP地址或者域名,在某些网络环境下,可能会使用端口映射的方式来访问局域网内部的KBE服务器,那么KBE在当前
        的机器上获得的外部地址是局域网地址,此时某些功能将会不正常。例如:账号激活邮件中给出的回调地址, 登录baseapp。
        注意:服务端并不会检查这个地址的可用性,因为无法检查。
        (Forced to specify an external IP-address or Domain-name, In some server environment, May use the port mapping to access KBE,
        So KBE on current machines on the external IP address may be a LAN IP address, Then some functions will not normal.
        For example: account activation email address given callback.
        Note: the availability of server does not check the address, because cannot check)
    -->
    <externalAddress>  </externalAddress>							<!-- Type: String -->
    
    <!-- 暴露给客户端的端口范围
        (Exposed to the client port range) 
    -->
    <externalTcpPorts_min> 20015 </externalTcpPorts_min>			<!-- Type: Integer -->
    <externalTcpPorts_max> 20019 </externalTcpPorts_max>			<!-- Type: Integer -->
    <externalUdpPorts_min> 20005 </externalUdpPorts_min>			<!-- Type: Integer -->
    <externalUdpPorts_max> 20009 </externalUdpPorts_max>			<!-- Type: Integer -->
</baseapp>

熟悉引擎的开发者应该知道,externalTcpPorts_minexternalTcpPorts_max的意义,UDP也类似。

externalUdpPorts_min int,暴露给客户端的UDP端口范围的最小值。

externalUdpPorts_max int,暴露给客户端的UDP端口范围的最大值。0表示无限制。


Copyright © 2018 Yolo Technologies. Publication: 2.0-025. Built: 2018-12-07.