[网络开发]RakNet文档翻译(2)——Connecting

作者: NickYang 分类: 技术文章,程序开发 发布时间: 2012-04-15 22:37

Connecting to other systems

 

找到连接的对象

下面是5种连接到其他系统的方法:

1.直接通过IP地址(前提是你已经知道该IP)

2.LAN广播

3.使用云服务器或者云客户端插件

4.使用大厅服务器或者房间插件(译者注:类型与游戏大厅和游戏房间的模式,想想QQ棋牌游戏)

5.使用DirectoryServer.php

方法1:直接使用IP地址

从编码的角度来说,最简单最容易的方法是硬编码的IP地址或者域名或者给出一个GUI要求用户输入他们相连接到其他系统的IP地址,大部分例子使用此方法。回顾网络游戏刚刚出现的时候使用此方法,也是当时唯一可用的方法。

优点:

  • 对程序员或者美工来说很简单,GUI界面可以很简单
  • 如果IP地址或者域名是固定的,例如你运行了一个专用服务器,这是一个正确的解决方案。

缺点:

  • 不够灵活
  • 用户只能与他们认识的人玩游戏

注意:在同一台电脑或者相同的应用程序,可以使用127.0.0.1或者 localhost连接到另外一个RakPeer实例。

方法2:局域网广播

RakNet支持广播一个数据包找到本地局域网内其他系统的功能,使用可选的数据包发送和检测应用程序,LANServerDiscovery例子展示了这个技术。

在RakPerrInterface.h中,Ping函数可以试下如下个功能

REMOTE_GAME_PORT可以是你关心的应用程序运行在其他系统上的任何端口。onlyReplyOnAcceptingConnections 是一个标志其他系统是否应该答复的布尔值,即使你没有连接到其他系统上的可用连接。

开放系统将会用ID_UNCONNECTED_PONG,看看下面的例子:

为了发送用户自定义数据,调用 RakPeer::SEtOfflinePingResponse( customUserData, lengthInBytes ); RakNet将会拷贝传给他的数据,同时返回值追加到ID_UNCONNECTED_PONG。(译者注:猜想是以位与的方式)

注意:在RakPeer.cpp中定义了一个硬编码的MAX_OFFLINE_DATA_LENGTH长度,它限制了用户数据长度。如果你的数据超过这个定义,修改该值并且重编译。

优点:

  • 你可以在程序启动的时候自动的加入游戏,不需要GUI或者其他用户交互
  • 在局域网内发现游戏的最佳方式

缺点:

  • 在一般的Internet网络上没用
  • 不如轻量级数据库插件灵活。

方法3:使用 云服务器/云客户端 插件

云服务器/云客户端不需要修改可直接作为服务器目录。

方法4:使用大厅服务器或者房间插件

大厅服务器为玩家交互和启动游戏提供了一个数据库驱动服务。它提供了一些功能,例如朋友,配对,邮件,排名,即时通信,快速匹配,房间和房间调整。

LobbyServerTest和LobbyClientTest例子展示了如何使用该功能。

优点:

  • 对于加油游戏的玩家来说比较灵活
  • 允许用户在启动游戏之前进行互动
  • 建立联系
  • 支持多个标题(称号)

缺点:

  • 需要一个单独并且专用的服务器来承载该插件,并且服务器需要数据库支持
  • 相比一个简单的游戏列表来说,该功能需要一个相对较大的并且复杂,需要在时间和编程上投入更多。

方法5:DirectoryServer.php

DirectoryServer.php 和相关的代码可以在Samples\PHPDirectoryServer2中找到。通过你的Web服务器去存储一个游戏的上传,同时该游戏是基于字串的信息,这种给出游戏列表的方法比较廉价。要获得更多的信息,请查看该功能的用户手册。

优点:

  • 不需要一台专用的服务器,只需要一个网页
  • 缺点:

不够灵活

  • 有时候不可用(可能需要多次查询请求)

尝试启动链接

一旦你知道了你要连接到的远程系统的IP地址,使用RakPeerInterface::Connect()尝试启动异步的连接,连接参数如下:

  • host 是一个IP地址或者域名
  • remotePort 是一个远程系统监听的端口,你传递给Startup()函数的端口
  • passwordData 是随着连接请求发送可选的二进制数据。如果该数据与传递给RakPeerInterface::SetPassword()函数的参数内容不匹配,远程系统会回应ID_INVALID_PASSWORD
  • passwordDataLength是passwordData的长度,单位是Byte
  • publicKey是远程系统上一个传递给InitializeSecurity()函数的公共键值。如果你不想使用,传0值
  • connectionSocketIndex是一个传递给RakPeer::Startup()中确定要发送的socket描述符数组中的索引.
  • sendConnectionAttempyCount是在放弃连接之前尝试发送的数据包次数。这是用于三种不同MTU大小的检测。默认值为12以为着每个MTU发送4次,这应该适合于任何形式的丢包了。值越低意味着收到ID_CONNECTION_ATTEMPT_FAILED越快。
  • timeBetweenSendConnectionAttemptsMS是指发送下一个连接尝试的间隔毫秒数。4倍的ping值是比较好的。
  • 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是通用的消息,他以为这没有建立与远程系统的沟通。可能的原因如下:

  • IP地址错误
  • 对方的系统可能没有运行RakNet或者没有调用RakPeerInterface::Startup()
  • 远程系统已经开始了RakNet,但是没用调用RakPeerInterface()::SetMaximumIncomingConnections()
  • 远程系统的防火墙阻止了你所选择端口上的UDP包
  • 远程系统上的路由器阻止了你所选择端口上的UDP包,查看NAT Punchthrough插件解决该问题
  • 在Windows Vista,网络驱动安全服务有时候会断掉UDP,并不是针对Raknet的,而是针对所有UDP连接,甚至是DirectPlay。该服务应该被回滚或者不要安装。
  • 开启了安全连接,并且你的系统安全检查失败
  • 你的IP地址在RakPeerInterface::AddToBanList()函数中被禁用了。注意一些插件,例如有自动禁用IP地址功能的Connection filter插件。

假设你已经连接上了,请转向下一部分:Createing Packets

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注