首页 > 代码库 > cocos2dx获取网络时间(一)

cocos2dx获取网络时间(一)

  今天在公司的cocos2dx项目中遇到一个需求,需要获取网络时间和系统时间对比,目的是防止用户更改系统时间进行某些非法操作 。

  那么cocos2dx怎么来获取网络时间呢 ?我整理的思路如下:

  (1)由一个web api可以返回当前的网络时间

  (2)cocos2dx通过http请求该api获取数据到本地

  (3)cocos2dx解析数据得到当前的网络时间

一:首先就需要一个web接口来提供网络时间的数据,我在这里自己搭建一个WCF服务返回需要的数据。

  新建WCF服务应用程序 , 项目命名为NetTimeService,将解决方案命名为NetTime:

技术分享

  在解决方案资源管理器新建WCF服务:

技术分享

  由于我们仅需要通过HTTP GET请求数据,故使用webHttpBinding即可。Web.config配置如下:

  

技术分享
 1 <system.serviceModel> 2     <services> 3       <service name="NetTimeService.NetTime"> 4         <endpoint binding="webHttpBinding" behaviorConfiguration="webGet" contract="NetTimeService.INetTime"/> 5       </service> 6     </services> 7     <behaviors> 8       <endpointBehaviors> 9         <behavior name="webGet">10           <webHttp/>11         </behavior>12       </endpointBehaviors>13       <serviceBehaviors>14         <behavior> 15           <serviceMetadata httpGetEnabled="false"/>16           <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->17           <serviceDebug includeExceptionDetailInFaults="false"/>18         </behavior>19       </serviceBehaviors>20     </behaviors>21     <serviceHostingEnvironment multipleSiteBindingsEnabled="false" />22   </system.serviceModel>
View Code

  WCF加入了对URI模板(UriTemplate)和JSON(WebMessageFormat.Json)的支持,使用WebGet对需要访问的方法WebDateTime()进行标记,并使用Json格式返回数据:

技术分享
 1 namespace NetTimeService 2 { 3     // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“INetTime”。 4     [ServiceContract] 5     public interface INetTime 6     { 7         [OperationContract] 8         [WebGet(UriTemplate = "/Time", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] 9         Time WebDateTime();10     }11 }
View Code

  我们需要获取的网络时间数据包括年,月,日,小时,分和秒,定义Time类:

  

技术分享
 1 namespace NetTimeService 2 { 3     [DataContractAttribute] 4     public class Time 5     { 6         [DataMemberAttribute] 7         public int Year { get; set; } 8         [DataMemberAttribute] 9         public int Month { get; set; }10         [DataMemberAttribute]11         public int Day { get; set; }12         [DataMemberAttribute]13         public int Hour { get; set; }14         [DataMemberAttribute]15         public int Minute { get; set; }16         [DataMemberAttribute]17         public int Second { get; set; }18         public Time(DateTime dt)19         {20             this.Year = dt.Year;21             this.Month = dt.Month;22             this.Day = dt.Day;23             this.Hour = dt.Hour;24             this.Minute = dt.Minute;25             this.Second = dt.Second;26         }27     }28 }
View Code

  WebDateTime()方法的实现如下:

  

技术分享
 1 namespace NetTimeService 2 { 3     // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“NetTime”。 4     // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 NetTime.svc 或 NetTime.svc.cs,然后开始调试。 5     public class NetTime : INetTime 6     { 7         public Time WebDateTime() 8         { 9             Time dt = new Time(DateTime.Now);10             return dt;11         }12     }13 }
View Code

  使用浏览器查看NetTime.svc,出现如下页面说明服务配置成功:

技术分享

 在浏览器地址栏输入http://localhost:23244/NetTime.svc/Time 便可以得到我们需要的json数据:

 技术分享

二:接下来便通过cocos2dx http访问服务来获取数据

  cocos2dx使用CCHttpClient对CURL进行封装,采用http的方式传输数据。

  在NetTime解决方案下新建cocos2dx项目,命名为NetTimeTest。

  使用HttpClient需要导入头文件:

   

#include "cocos-ext.h"USING_NS_CC_EXT;

  在HelloWorldScene.cpp的init()方法中添加如下代码:

  

技术分享
1 CCHttpRequest * request = new CCHttpRequest();2 request->setUrl("http://localhost:23244/NetTime.svc/Time");3 request->setRequestType(CCHttpRequest::kHttpGet);4 request->setTag("WebTime");5 request->setResponseCallback(this, httpresponse_selector(HelloWorld::onHttpComplete));6 CCHttpClient::getInstance()->send(request);
View Code

  在onHttpComplete回调方法中:

  

技术分享
 1 void HelloWorld::onHttpComplete(CCHttpClient * sender, CCHttpResponse * response) 2 { 3     CCHttpClient::getInstance()->release(); 4     if (!response) 5         return; 6     if (0 != strlen(response->getHttpRequest()->getTag())) 7     { 8         CCLog("%s completed", response->getHttpRequest()->getTag()); 9     }10     int statusCode = response->getResponseCode();11     char statusString[64] = {};12     sprintf(statusString, "HTTP Status: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());13     CCLog("%s", statusString);14     if (!response->isSucceed())15     {16         CCLog("response failed");17         CCLog("error buffer:%s", response->getErrorBuffer());18         return;19 20     }21     std::vector<char> * buffer = response->getResponseData();22     std::string str;23     for (unsigned i = 0; i < buffer->size(); i++)24     {25         char a = (*buffer)[i];26         str.append(1, a);27     }28     CCLog("%s", str.c_str());29 }
View Code

  运行cocos2dx项目,可以在输出控制台看到 成功的通过cocos2dx获取到了网络时间:

技术分享

三:但是得到的数据是Json格式,并不能直接在项目里使用,就需要进行json数据的解析:

  我在这里使用的是rapidjson,包含在cocostudio工程中。

  同样先导入头文件:

  

#include "CocoStudio\Json\rapidjson\rapidjson.h"
using namespace rapidjson;

  定义readJson方法解析json数据:

技术分享
 1 void HelloWorld::readJson(string jsonStr) 2 { 3     Document doc; 4     doc.Parse<0>(jsonStr.c_str()); 5     if (!doc.IsObject()) 6         return; 7     if (doc.HasMember("Year") && doc.HasMember("Month") && doc.HasMember("Day") && doc.HasMember("Hour") && doc.HasMember("Minute") && doc.HasMember("Second")) 8     { 9         const Value &pYear = doc["Year"];10         int    year = pYear.GetInt();11         const Value &pMonth = doc["Month"];12         int month = pMonth.GetInt();13         const Value &pDay = doc["Day"];14         int day = pDay.GetInt();15         const Value &pHour = doc["Hour"];16         int hour = pHour.GetInt();17         const Value &pMinute = doc["Minute"];18         int minute = pMinute.GetInt();19         const Value &pSecond = doc["Second"];20         int second = pSecond.GetInt();21         char timeStr[50];22         sprintf(timeStr, "NetTime  %d-%d-%d %d:%d:%d",23             year, month, day,hour, minute, second);24         CCLabelTTF *timeLabel = CCLabelTTF::create(timeStr, "Arial", 18);25         timeLabel->setPosition(ccp(240, 50));26         this->addChild(timeLabel);27     }28 }
View Code

  在onHttpComplete方法最后添加对readJson方法的调用:

  技术分享

  运行项目:

  技术分享

  Demo下载 :NetTime.zip

  本文在cocos2dx中使用的方法参考了他人博客:

  Cocos2d-x笔记 CCHttpCleint网络请求 

  cocos2dx 读取json及解析 

  但本文主要提供了一种解决问题的思路供大家参考。 如果你对cocos2dx获取网络时间有更好的解决方案,欢迎提出和大家一起讨论。

  最后的问题,如果要在另外的项目中使用上面的方法,那么应该怎么对这些方法进行封装呢 ?在下一篇文章里我会和大家揭晓。

cocos2dx获取网络时间(一)