最近要存放png图片在本地 使用http协议 结果是一个头两个脑袋大
网上找了很多都是ftp的 然后最后仔细的研究了下 还和朋友反复检查 终于把http下接收二进制数组并使用sqlite3来存放信息以及更新信息w完成了更多游戏的随时有网络的时候可以不用管理客户端的最佳通用功能
1:libcurl的使用 前面的文章提到了很多 关于建立http的连接以及post、get的使用 还有tcp/ip通信
还是用代码罗列下吧 我最喜欢就是用代码说事 直观易懂
unsignedchar bufff[888888]; //接收到的二进制数据缓存
unsigned int l; //判断接收到了多少二进制数据
unsignedchar* get(conststd::string &url)const
{
memset(bufff,0,88888);//预估数据长度 稍微夸张了点 使用了印度程序手法 保证非常规性的时候 内存够用 当然这个需要私下进行测试 然后选择最佳缓存大小
l =0;
CURL *curl =curl_easy_init();
if(curl ==NULL)
{
cocos2d::CCLog("curl_easy_init failed");
l =0;
returnbufff;
}
curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorBuffer);
curl_easy_setopt(curl,CURLOPT_HEADER,0);
curl_easy_setopt(curl,CURLOPT_URL, url.c_str());
curl_easy_setopt(curl,CURLOPT_TIMEOUT,30);//30秒超时
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,writer);//绑定回调函数
curl_easy_setopt(curl,CURLOPT_WRITEDATA, &bufff);//确定数据类型
CURLcode code =curl_easy_perform(curl); //执行上面的设置也就是说开始通信
if(code !=CURLE_OK)
{
cocos2d::CCLog("curl_easy_perform failed: %d",code);
// if (CURLE_OPERATION_TIMEDOUT == code) //连接失败 超时
{
memset(bufff,1,1);
returnbufff;
}
l =0; //根据l判断数据是否接收成功
}
curl_easy_cleanup(curl);
returnbufff;
}
//回调函数有数据返回的时候就会调用这个函数
int writer(unsignedchar *data,size_t size,size_t nmemb,unsignedchar *writerData)
{
int realsize = size * nmemb;
memcpy(bufff+l, data, realsize);
l += realsize;
return realsize;
}
int getBytesL(){returnl;};
2.数据处理
//先联网获取
char addstr[100];
std::string path =hotHttpPath;
sprintf(addstr,"?gameId=1");
path.append(addstr);
CCLOG("request getURL:%s",path.c_str());
unsignedchar* bytes =get(path);
if (getBytesL() ==0)
{
//网络连接失败或者错误
returnfalse;//读取本地数据
}
else
{ //数据接收成功
//TODO处理数据
//使用前面的数据转换 bytes转为自己需要的数据类型
//如果你的服务器也是java那么请看前面的网络字节高低位转换就可以完成数据的翻译
}
3:读取本地数据 sqlite3存入本地的时候 最好是存图片的相对或者绝对路劲
接收到的图片png、jpg等格式直接写入文件 并以png、jpg后缀 就直接得到了图片 然后你想那个啥就那个啥吧
数据写入本地文件代码
bool savePng(constchar *pngName,constunsignedchar *pngDatas,constunsignedint datasLength)const
{
std::string savePath =defaultPngPath + pngName;
if (access(savePath.c_str(),0) ==0) //文件存在先删除
{
remove(savePath.c_str());
}
FILE* pf =fopen(savePath.c_str(),"wb");
if (pf)
{
fwrite(pngDatas,1, datasLength, pf);
fclose(pf);
return true;
}
return false;
不多说直接看代码:
CURL *curl;
CURLcode res;
const char *request = "GETas.xxxxE测试发送";
curl_socket_t sockfd; /* socket */
long sockextr;
size_t iolen;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1");
curl_easy_setopt(curl, CURLOPT_PORT, 7102);
/* Do not do the transfer - only connect to host */
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
res = curl_easy_perform(curl);
if(CURLE_OK != res)
{
printf("Error: %s\n", strerror(res));
return 1;
}
/* Extract the socket from the curl handle - we'll need it for waiting.
* Note that this API takes a pointer to a 'long' while we use
* curl_socket_t for sockets otherwise.
res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockextr);
if(CURLE_OK != res)
{
printf("Error: %s\n", curl_easy_strerror(res));
return 1;
}
sockfd = sockextr;
/* wait for the socket to become ready for sending */
//if(!wait_on_socket(sockfd, 0, 60000L))
//{
// printf("Error: timeout.\n");
// return 1;
//}
puts("Sending request.");
/* Send the request. Real applications should check the iolen
* to see if all the request has been sent */
res = curl_easy_send(curl, request, strlen(request), &iolen);
if(CURLE_OK != res)
{
printf("Error: %s\n", curl_easy_strerror(res));
return 1;
}
puts("Reading response.");
/* read the response */
for(;;)
{
char buf[1024];
// wait_on_socket(sockfd, 1, 60000L);
res = curl_easy_recv(curl, buf, 1024, &iolen);
if(CURLE_OK == res)
{
printf("Received %d bytes.\n", iolen);
}
}
/* always cleanup */
curl_easy_cleanup(curl);
}
对于错误的处理
if( res ==CURLE_OK &&iolen >0 )
{
//处理数据
printf("Received %lu bytes.\n",iolen);
}
elseif( res ==CURLE_RECV_ERROR)
{
CCAssert("Client Miss Connect",NULL);
printf("socket state error #0 (%d)", res );
//重连
}
elseif (res ==CURLE_AGAIN )
{
}
elseif(res ==CURLE_UNSUPPORTED_PROTOCOL)
{
//重连
}
elseif(res ==CURLE_OPERATION_TIMEDOUT)
{
//超时
printf("连接超时。");
}