libcurl http 接收二進制數據通信


最近要存放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)

{

  //網絡連接失敗或者錯誤

    return false;//讀取本地數據       

}     

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("連接超時。");

        }

 

 

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM