首页 > 代码库 > 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>
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 }
我们需要获取的网络时间数据包括年,月,日,小时,分和秒,定义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 }
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 }
使用浏览器查看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);
在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 }
运行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 }
在onHttpComplete方法最后添加对readJson方法的调用:
运行项目:
Demo下载 :NetTime.zip
本文在cocos2dx中使用的方法参考了他人博客:
Cocos2d-x笔记 CCHttpCleint网络请求
cocos2dx 读取json及解析
但本文主要提供了一种解决问题的思路供大家参考。 如果你对cocos2dx获取网络时间有更好的解决方案,欢迎提出和大家一起讨论。
最后的问题,如果要在另外的项目中使用上面的方法,那么应该怎么对这些方法进行封装呢 ?在下一篇文章里我会和大家揭晓。
cocos2dx获取网络时间(一)