PHP 目录服务器概述
使用共享的Web主机给出游戏列表
Lightweight数据库插件功能强大,但是它要求一个一台专用的服务器运行RakNet实例。在有些情况下,这个要求无法满足,并且运行专用服务器额负担也是不可取的。对于这些情况,RakNet提供了一个DirectoryServer.php,它可以再Sample\PHPDirecotory目录下找到。
设置web服务器,仅仅需要将Samples\PHPDirectoryServer\Directory.php上传到你的PHP的web主机即可(webhost可以是任何标准的web服务器)。转到你新上传的webpage,点击显示按钮,输入密码和其他的想要的设置参数。
C++代码更加复杂。首先,你需要定义一个TCPInterface的实例,并且启动该实例。这是通常的TCP通信必备。
TCPInterface tcp;
tcp.Start(0, 64);
第二,还需要一个HTTPConnection实例,它用于通过TCPInterface实例与webpages进行通信。
HTTPConnection httpConnection(tcp, "jenkinssoftware.com");
第三,你需要定义一个PHPDirectoryServer实例。它用于解析和与指定的DirectoryServer.php通信。
PHPDirectoryServer phpDirectoryServer(httpConnection, "/raknet/DirectoryServer.php");
转到http://www.jenkinssoftware.com/raknet/DirectoryServer.php可以实际看一看页面效果。
然后你可以设置列,上传你的表或下载已经存在的表:
// 使用columnname / value设置域值
phpDirectoryServer.SetField("beehive","inthewater");
// 上传前面设置的域,要用到游戏名称,游戏端口,和密码
phpDirectoryServer.UploadTable(50, "Game name", 1234, "");
// 下载上传的服务器
phpDirectoryServer.DownloadTable("");
更新系统,应该从TCPInterface向两个接口传递数据包,并且要调用Update()。TCP数据报没有包含一个完整的webpage响应,webpage可能包含错误代码,来自webpage的信息不全是与我们的服务器相关的使得事情变得比较复杂。例子详细说明了如何处理,如下的代码是一个简要的摘录:
Packet *packet = tcp.Receive();
if(packet)
{
// 在这个例子中,这一行不是必须的,但是如果我们正在使用TCPInterface,我们想要确保我们仅仅给它一个消息表明我们我们的本条连接。
if (packet->systemAddress==httpConnection.GetServerAddress())
{
// 从一个web服务器一条请求可能返回多个数据报。当最后的数据报达到时, ProcessFinalTCPPacket会返回真
if (httpConnection.ProcessFinalTCPPacket(packet))
{
int code;
RakNet::RakString data;
/// 检查请求已经处理,没有错误代码
if (httpConnection.HasBadResponse(&code, &data)==false)
{
// 好的响应,让PHPDirectoryServer类处理该数据
// 如果resultCode不是空字符串,那么我们得到了一些东西而非表
// (例如删除行成功提示,或消息仅仅是HTTP的并不是本类的数据).
HTTPReadResult readResult = phpDirectoryServer.ProcessHTTPRead(httpResult);
if (readResult==HTTP_RESULT_GOT_TABLE)
{
/// 获得了一个内部存储的表,打印出来。
char out[10000];
const DataStructures::Table *games = phpDirectoryServer.GetLastDownloadedTable();
games->PrintColumnHeaders(out,sizeof(out),',');
printf("COLUMNS: %s\n", out);
// 打印表的每一行
for (unsigned i=0; i < games->GetRowCount(); i++)
{
games->PrintRow(out,sizeof(out),',',true, games->GetRowByIndex(i,NULL));
printf("ROW %i: %s\n", i+1, out);
}
}
}
}
}
// 释放数据报
tcp.DeallocatePacket(packet);
}
httpConnection.Update();
phpDirectoryServer.Update();
某些列被保存,给你返回一个查询。这些列名字不允许用于终端用户,如果参数使用会发生assert(断言)。
// 带有这个头的列包含了游戏的名字,传递给UploadTable()
static const char *GAME_NAME_COMMAND="__GAME_NAME";
// 带有这个头的列包含了游戏的端口,传递给UploadTable()
static const char *GAME_PORT_COMMAND="__GAME_PORT";
// 从PHP服务器返回,表明了这行最后更新的时间。
static const char *LAST_UPDATE_COMMAND="__SEC_AFTER_EPOCH_SINCE_LAST_UPDATE";
// 删除一行的命令
static const char *DELETEME_COMMAND="__DELETE_ROW";
// 传递给PHP服务器,它是作为密码
static const char *GAME_PASSWORD_COMMAND="__PHP_DIRECTORY_SERVER_PASSWORD";
// 这一列传递给PHP服务器,作为在自动推出之前多长时间列出这个服务器。
static const char *GAME_TIMEOUT_COMMAND="__GAME_LISTING_TIMEOUT";
__SYSTEM_ADDRESS参数被返回表明外部的一个IP用于上传webpage。
注意由于技术限制,在同一个时间仅仅允许一个上传。如果你的服务器仅仅管理一个游戏,那么这个限制不是问题。当一个上传正在进行,如果调用了PHPDirectoryServer::UploadTable()方法会覆盖掉这前一个上传。当HTTPConnectionBusy()返回false时可以执行另外一个上传过程。
By 北洋小郭
转载请注明出处,请勿用于商业用途,谢谢!