标签:
今天在公司的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中使用的方法参考了他人博客:
但本文主要提供了一种解决问题的思路供大家参考。 如果你对cocos2dx获取网络时间有更好的解决方案,欢迎提出和大家一起讨论。
最后的问题,如果要在另外的项目中使用上面的方法,那么应该怎么对这些方法进行封装呢 ?在下一篇文章里我会和大家揭晓。
标签:
原文地址:http://www.cnblogs.com/lhyEmpty/p/4188678.html