当前位置: 首页 > 工具软件 > Raknet > 使用案例 >

一日一点RakNet(11)--Connecting

艾意蕴
2023-12-01
 

连接到其他的系统

 

寻找连接目标

 

有5个方式来发现要连接到的系统:

       1. 直接输入IP地址(这个广为人知)。

       2. LAN广播

       3. 使用ClientServer/CloudClient插件

       4. 使用游戏大厅服务器或房间插件

       5. 使用目录服务器DirectoryServer

选择1:输入IP地址

       从编码的角度看,最简单,最容易的方式就是将IP地址或域名硬编码,或使用GUI询问用户,让他们来输入他们想要连接的系统的IP地址。很多例子使用这种方法。游戏刚刚出来的时候支持这种方式,这种方式是唯一可用的方式。

       优势:

       1. 对于编程人员和美工的要求较少,GUI可以很简单。

       2. 如果IP地址或域名是固定的,例如运行的是一个专用服务器,这个就是最好的解决方案。

       不足:

       1. 缺乏灵活性

       2. 用户仅仅可以与他们知道的人们玩游戏。

       注意:要连接到本机上的RakPeer实例或其他相同的应用程序,IP地址要使用127.0.0.1或localhost。

 

选择2:LAN广播

       RakNet支持在局域网中广播一个数据报发现其他的系统的功能,使用可选的数据来发送和检索相似的应用程序。例子LANServerDiscovery说明了这项技术。

       在RakPeerInterface中,Ping函数可以做到这些,如下所述:

       rakPeer->Ping("255.255.255.255", REMOTE_GAME_PORT, onlyReplyOnAcceptingConnections);

       REMOTE_GAME_PORT应该是其他系统上你关心的应用程序运行的端口。onlyReplyOnAcceptConnections是一个布尔值,来标识其他系统是否需要回复,即使你没有可用连接连接到该系统。

       开放系统会回复ID_UNCONNECTED_PONG,例如下面的例子:

if (p->data[0]==ID_UNCONNECTED_PONG)
{
    RakNet::TimeMS time;
    RakNet::BitStream bsIn(packet->data,packet->length,false);
    bsIn.IgnoreBytes(1);
    bsIn.Read(time);
    printf("Got pong from %s with time %i\n", p->systemAddress.ToString(), RakNet::GetTime() - time);
}

       为了发送用户数据,调用RakPeer::SetOfflinePingResponse(customUserData, lengthInBytes);,RakNet会拷贝传递给它的数据,然后将数据返回回来追加到ID_UNCONNECTED_PONG。

       注意:在RakPeer.cpp中有一个硬编码的MAX_OFFLINE_DATA_LENGTH限制了用户的数据长度。如果数据比这个值大,修改这个值,重新进行编译。

       优点:

       1. 在系统启动后,可以自动加入游戏,不需要GUI或用户交互。

       2. 在LAN上最好的寻找游戏的方法。

       不足:

       1. 在一般的因特网上不可用

       2. 不如lightweight database 插件灵活

 

选项3:使用CloudServer/CloudClient插件

       不用修改,CloudServer/CloudClient插件直接就可以作为目录服务器。

选项4:使用游戏大厅服务器或房间插件

       游戏大厅服务器提供了一个数据库驱动服务器,用于交互和开始游戏。它提供了一些功能,例如好友,配对,邮件,排名,即时通信,快速配对,房间,或房间协调。

       参考Lobby2Server_PGSQL和Lobby2Client中对这项功能的使用方法。

       优势:

       1. 玩家加入游戏最灵活的处理方式

       2. 允许用户在开始游戏之前进行交互

       3. 建立社区

       4. 支持多个标题

       不足

       1. 需要一个分离的专用服务器来承载这个插件,服务器需要有数据库支持。

       2. 功能相对于简单的游戏列表较大,且复杂,需要时间和编程方面投入更多。

选择5: DirectoryServer.php

       DirectoryServer.php和相关的代码可以在Samples\PHPDirectoryServer2中找到。这种方式是给出游戏列表比较廉价的方式,游戏上线后使用web服务器来存储,游戏信息是使用字符串来给出。获得更多信息,参考这个功能的参考手册。

       优点:

       1. 不需要专用的服务器,仅需要一个web页

       缺点:

       1. 不灵活

       2. 有时不可用(需要多次访问)

 

发起连接尝试

一旦知道了想要连接的远端系统的IP地址,使用RakPeerInterface::Connect()方法初始化一个异步的连接尝试,连接参数如下:

       ConnectionAttemptResult Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey=0, unsigned connectionSocketIndex=0, unsigned sendConnectionAttemptCount=6, unsigned timeBetweenSendConnectionAttemptsMS=1000, RakNet::TimeMS timeoutTime=0 )

       1. host是一个IP地址,或域名

       2. remotePort是远端系统监听的端口,传递给Startup()函数的端口参数。

       3. passwordData是随着连接请求发送的二进制数据。如果这个参数与传递给RakPeerInterface::SetPassword()的参数不同,远端系统会回复ID_INVALID_PASSWORD。

       4. passwordDataLength是passwordData的长度,单位是字节。

       5. publicKey 是远端系统上传递给InitializeSecurity()函数的公用密钥参数。如果你不适用,传递0。

       6. connectionSocketINdex是你要发送的客户端的Socket在传递给RakPeer::Startup()函数的socket描述符的数组中的索引。

       7. sendConnectionAttemptCount是在确定无法连接前要做出的发送尝试次数。这个也用于MTU检测,使用3个不同的MTU大小。默认的值12意味着发送每个MTU四次,这对于容忍任何原因的包丢失也是足够的了。更低的值意味着ID_CONNECTION_ATTEMPT_FAILED会更快返回。

       8. timeBetweenSendConnectionAttemptsMS是进行另外一次连接尝试要等待的毫秒数。比较好的值是4倍的ping值。

       9. 如果消息不能发送,在丢掉远端系统之前,为这次连接,timeoutTime指出了要等待多少毫秒。默认值是0,意味着使用SetTimeoutTime()方法中的全局值。

       连接尝试成功Connect()会返回CONNECTION_ATTEMPT_STARTED值,如果失败会返回其他的值。

       注意:Connect()返回TRUE并不意味着已经连接成功。如果连接成功,应该会返回ID_CONNECTION_REQUEST_ACCEPTED。否则,会收到一条错误消息。

      

连接消息作为Packet::data结构的第一个字节返回

 

连接关闭: ID_DISCONNECTION_NOTIFICATION, ID_CONNECTION_LOST
新的连接: ID_NEW_INCOMING_CONNECTION, ID_CONNECTION_REQUEST_ACCEPTED
连接尝试失败: ID_CONNECTION_ATTEMPT_FAILED, ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY, ID_OUR_SYSTEM_REQUIRES_SECURITY, ID_PUBLIC_KEY_MISMATCH, ID_ALREADY_CONNECTED, ID_NO_FREE_INCOMING_CONNECTIONS, ID_CONNECTION_BANNED, ID_INVALID_PASSWORD, ID_INCOMPATIBLE_PROTOCOL_VERSION, ID_IP_RECENTLY_CONNECTED

 

解决ID_CONNECTION_ATTEMPT_FAILED错误

       ID_CONNECTION_ATTEMPT_FAILED是一条概述性消息,意味着与远端系统没有建立连接。可能的原因包括如下几方面:

       1. IP地址错误

       2. 远端系统没有运行RAkNet,或RakPeerInterface::Startup()在这个系统上没有调用。

       3. 远端系统启动了RakNet,但是RakPeerInterface::SetMaximumIncomingConnection没有调用。

       4. 防火墙阻止了你选择的端口上的UDP数据包。

       5. 远端系统的一个路由器阻塞了进入你选择的端口上的UDP数据包。参考NAT Punchthrough插件解决这个问题。

       6. 在Windows Vista上,网络驱动安全服务器包有事破坏了UDP,不仅仅是RakNet,甚至是DirectPlay。这个服务包应该关闭或者不要安装。

       7. Secure Connections启用了,但是安全检查不正确。

       8. 你的iP地址被RakPeerInterface::AddToBanList()函数禁止了。注意有些插件例如Connection filter,有可选的自动禁止IP地址的功能。

 

假设你已经能够连接上了,转向下一部分:Creating Packets

 

By  北洋小郭

 类似资料: