一日一点RakNet(60)--PHP Directory Server(目录服务器)

来源:互联网 发布:2015网络事件营销案例 编辑:程序博客网 时间:2024/05/10 02:36

PHP目录服务器概述

 

使用共享的Web主机给出游戏列表

       Lightweight数据库插件功能强大,但是它要求一个一台专用的服务器运行RakNet实例。在有些情况下,这个要求无法满足,并且运行专用服务器额负担也是不可取的。对于这些情况,RakNet提供了一个DirectoryServer.php,它可以再Sample\PHPDirecotory目录下找到。

       设置web服务器,仅仅需要将Samples\PHPDirectoryServer\Directory.php上传到你的PHPweb主机即可(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北洋小郭

转载请注明出处,请勿用于商业用途,谢谢!

 

 

原创粉丝点击