cocos2dx_CurlTest分析

来源:互联网 发布:caffe接口matlab 编辑:程序博客网 时间:2024/06/01 09:21


1.概述
Curl,是一套可以访问各种网络协议服务的API,
官方网站:http://curl.haxx.se


在cocos2d-x-3.10中,你可以在如下目录找到curl.h:
cocos2d-x-3.10/external/curl/include/android/curl
cocos2d-x-3.10/external/curl/include/ios/curl


注意:cocos2dx3.10中的Http连接的底层就是curl实现的,具体请看cocos2dx3.10 lua中的测试用例XMLHttpRequestTest。


2.实例
cocos2d-x提供了curl测试用例,在如下地址:
cocos2d-x-3.10/tests/cpp-tests/Classes/CurlTest


CurlTest.h---------------
#include "cocos2d.h"
#include "../BaseTest.h"


DEFINE_TEST_SUITE(CurlTests);


class CurlTest : public TestCase
{
public:
    CREATE_FUNC(CurlTest);


    CurlTest();
    ~CurlTest();


    void onTouchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event  *event);


private:
    cocos2d::Label* _label;
};


CurlTest.cpp---------------
#include "platform/CCPlatformConfig.h"
#if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) && (CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID)
#include "CurlTest.h"
#include "stdio.h"
#include "stdlib.h"
#include "curl/curl.h"


USING_NS_CC;


CurlTests::CurlTests(){
    ADD_TEST_CASE(CurlTest);
}


CurlTest::CurlTest(){
    auto label = Label::createWithTTF("Curl Test", "fonts/arial.ttf", 28);
    addChild(label, 0);
    label->setPosition(VisibleRect::center().x, VisibleRect::top().y-50);


    auto listener = EventListenerTouchAllAtOnce::create();
    listener->onTouchesEnded = CC_CALLBACK_2(CurlTest::onTouchesEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);


    // create a label to display the tip string
    _label = Label::createWithTTF("Touch the screen to connect", "fonts/arial.ttf", 22);
    _label->setPosition(VisibleRect::center());
    addChild(_label, 0);
    
    _label->retain();
}


//用来保存要发送的数据的结构体
struct MemoryStruct {
  char *memory;
  size_t size;
};


//写数据
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp){
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
  if(mem != null){ //这里为了防止抛出异常,加了一个判断
 mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
 if(mem->memory == NULL) {
/* out of memory! */ 
printf("not enough memory (realloc returned NULL)\n");
return 0;
 }
 
 memcpy(&(mem->memory[mem->size]), contents, realsize);
 mem->size += realsize;
 mem->memory[mem->size] = 0;
  }
 
  return realsize;
}
 
// the test code is
// http://curl.haxx.se/mail/lib-2009-12/0071.html
void CurlTest::onTouchesEnded(const std::vector<Touch*>& touches, Event  *event){
    CURL *curl; //首先,使用CURL必须要创建一个CULR指针,它是CURL的全局句柄。
    CURLcode res; //这里定义一个CURL库中API的返回值,用于取得API调用的结果。
    char buffer[10]; //错误码的缓冲区


    struct MemoryStruct chunk;
    chunk.memory = (char*)malloc(1);  /* will be grown as needed by the realloc above */
    chunk.size = 0;    /* no data at this point */

//第一步:初始化CURL,取得初始化成功后的CURL指针。
    curl = curl_easy_init();
    if (curl) {
//第二步,设定我们用此CURL指针来完成的动作。参数一为CURL指针,参数二为相应
//的动作类型枚举,这个枚举值在curl.h中定义,比如本例中的CURLOPT_URL,定义
//为CINIT(URL,  OBJECTPOINT, 2),即联接一个网站的HTTP服务。参数三为动作对应
//的数据参数,这里是网站的URL地址。
        curl_easy_setopt(curl, CURLOPT_URL, "http://webtest.cocos2d-x.org/curltest");
//code from http://curl.haxx.se/libcurl/c/getinmemory.html

        /* we pass our 'chunk' struct to the callback function */
//保存回调函数得到的数据
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

//If we don't provide a write function for curl, it will recieve error code 23 on windows.
        //将得到的数据传递到回调函数里
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);


//第三步,执行上面设定的动作处理。返回结果放在res中。
        res = curl_easy_perform(curl);

        /* always cleanup */
//最后一步,清除CURL指针,结束对CURL库的使用。
        curl_easy_cleanup(curl);

        if (res == 0){ //如果动作处理成功,则显示联结成功,但没有开始接收任何数据。  
            _label->setString(StringUtils::format("Connect successfully!\n%s", chunk.memory));
        }else{ //如果动作处理失败,打印错误码。
            sprintf(buffer,"code: %i",res);
            _label->setString(buffer);
        }
    }else {
        _label->setString("no curl");
    } 
}


CurlTest::~CurlTest(){
    _label->release(); //对占用的标题文本标签计数器减一。不再继续占用以使它能够正常被释放。
}
#endif


3.函数分析
3.1.curl_easy_perform()
当你调用的时候,libcurl会执行所有的必要动作,当开始上传的时候,它会调用我的回调函数。
程序会尽可能多,尽可能快的的上传数据。回调函数返回写入缓冲区的数据的大小。
返回0的时候就表示上传结束了。


3.2.回调函数
如果你想自己处理得到的数据而不是直接显示在标准输出里,就需要自己写回调函数,如下:
size_t write_data(char *bufptr, size_t size, size_t nitems, void *userp);


bufptr 参数指向一段准备上传数据的缓冲区,nitem是这段缓冲区的大小,userp是一个用户自
定义指针,libcurl不对该指针作任何操作,它只是简单的传递该指针。
可以使用该指针在应用程序与libcurl之间传递信息。
以下函数的chunk就是该指针。
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);


3.3.
当你用字符串设置 curl_easy_setopt(),libcurl会复制这个字符串的一个副本,所以你在设
置后不用再保存那个字符串的内存。
使用 CURLOPT_WRITEDATA,libcurl不会处理你所传递的数据。


3.4.显示进度
通过将CURLOPT_NOPROGRESS设置为0开启进度支持。该选项默认值为1。对大多数应用程序,我们
需要提供一个进度显示回调。libcurl会不定期的将当前传输的进度通过回调函数告诉你的程序。


通过CURLOPT_PROGRESSFUNCTION注册该回调函数。
参数clientp是一个用户自定义指针,应用程序通过CURLOPT_PROCESSDATA
属性将该自定义指定传递给libcurl。libcurl对该参数不作任何处理,
只是简单将其传递给回调函数。


curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, 0L);


//回调函数原型
int progress_callback(void *clientp,double dltotal,double dlnow,double ultotal,double ulnow);


3.5.
每次执行完curl_easy_perform,licurl会继续保持与服务器的连接。接下来的请求可以使用这
个连接而不必创建新的连接(如果目标主机是同一个的话)。这样可以减少网络开销。 
即使连接被释放了,libcurl也会缓存这些连接的会话信息,这样下次再连接到目标主机上时,
就可以使用这些信息,从而减少重新连接所需的时间。


4.curl_easy_perform()返回值说明
CURLE_OK = 0,                  /* 0 */                                         0:    no error  
CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */                                         1:    unsupported protocol  
CURLE_FAILED_INIT,             /* 2 */                                         2:    failed init  
CURLE_URL_MALFORMAT,           /* 3 */                                         3:    URL using bad/illegal format or missing URL  
CURLE_URL_MALFORMAT_USER,      /* 4 - NOT USED */                              4:    unknown error  
CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */                                         5:    couldn't resolve proxy name  
CURLE_COULDNT_RESOLVE_HOST,    /* 6 */                                         6:    couldn't resolve host name  
CURLE_COULDNT_CONNECT,         /* 7 */                                         7:    couldn't connect to server  
CURLE_FTP_WEIRD_SERVER_REPLY,  /* 8 */                                         8:    FTP: weird server reply  
CURLE_FTP_ACCESS_DENIED,       /* 9 a service was denied by the FTP server     9:    FTP: access denied  
due to lack of access - when login fails    
this is not returned. */    
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 - NOT USED */                        10:    unknown error  
CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */                                       11:    FTP: unknown PASS reply  
CURLE_FTP_WEIRD_USER_REPLY,    /* 12 */                                       12:    FTP: unknown USER reply  
CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */                                       13:    FTP: unknown PASV reply  
CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */                                       14:    FTP: unknown 227 response format  
CURLE_FTP_CANT_GET_HOST,       /* 15 */                                       15:    FTP: can't figure out the host in the PASV response  
CURLE_FTP_CANT_RECONNECT,      /* 16 */                                       16:    FTP: can't connect to server the response code is unknown  
CURLE_FTP_COULDNT_SET_BINARY,  /* 17 */                                       17:    FTP: couldn't set binary mode  
CURLE_PARTIAL_FILE,            /* 18 */                                       18:    Transferred a partial file  
CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */                                       19:    FTP: couldn't retrieve (RETR failed) the specified file  
CURLE_FTP_WRITE_ERROR,         /* 20 */                                       20:    FTP: the post-transfer acknowledge response was not OK  
CURLE_FTP_QUOTE_ERROR,         /* 21 */                                       21:    FTP: a quote command returned error  
CURLE_HTTP_RETURNED_ERROR,     /* 22 */                                       22:    HTTP response code said error  
CURLE_WRITE_ERROR,             /* 23 */                                       23:    failed writing received data to disk/application  
CURLE_MALFORMAT_USER,          /* 24 - NOT USED */                            24:    unknown error  
CURLE_UPLOAD_FAILED,           /* 25 - failed upload "command" */             25:    upload failed (at start/before it took off)  
CURLE_READ_ERROR,              /* 26 - could open/read from file */           26:    failed to open/read local data from file/application  
CURLE_OUT_OF_MEMORY,           /* 27 */                                       27:    out of memory  
/* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error    
  instead of a memory allocation error if CURL_DOES_CONVERSIONS    
  is defined    
*/    
CURLE_OPERATION_TIMEOUTED,     /* 28 - the timeout time was reached */        28:    a timeout was reached 
CURLE_FTP_COULDNT_SET_ASCII,   /* 29 - TYPE A failed */                       29:    FTP could not set ASCII mode (TYPE A)  
CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */           30:    FTP command PORT failed  
CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */             31:    FTP command REST failed  
CURLE_FTP_COULDNT_GET_SIZE,    /* 32 - the SIZE command failed */             32:    FTP command SIZE failed  
CURLE_HTTP_RANGE_ERROR,        /* 33 - RANGE "command" didn't work */         33:    a range was requested but the server did not deliver it  
CURLE_HTTP_POST_ERROR,         /* 34 */                                       34:    internal problem setting up the POST 
CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */      35:    SSL connect error  
CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */            36:    couldn't resume download  
CURLE_FILE_COULDNT_READ_FILE,  /* 37 */                                       37:    couldn't read a file:// file  
CURLE_LDAP_CANNOT_BIND,        /* 38 */                                       38:    LDAP: cannot bind  
CURLE_LDAP_SEARCH_FAILED,      /* 39 */                                       39:    LDAP: search failed  
CURLE_LIBRARY_NOT_FOUND,       /* 40 */                                       40:    a required shared library was not found  
CURLE_FUNCTION_NOT_FOUND,      /* 41 */                                       41:    a required function in the shared library was not found  
CURLE_ABORTED_BY_CALLBACK,     /* 42 */                                       42:    the operation was aborted by an application callback  
CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */                                       43:    a libcurl function was given a bad argument  
CURLE_BAD_CALLING_ORDER,       /* 44 - NOT USED */                            44:    unknown error  
CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */            45:    failed binding local connection end  
CURLE_BAD_PASSWORD_ENTERED,    /* 46 - NOT USED */                            46:    unknown error  
CURLE_TOO_MANY_REDIRECTS ,     /* 47 - catch endless re-direct loops */       47:    number of redirects hit maximum amount  
CURLE_UNKNOWN_TELNET_OPTION,   /* 48 - User specified an unknown option */    48:    User specified an unknown option  
CURLE_TELNET_OPTION_SYNTAX ,   /* 49 - Malformed telnet option */             49:    Malformed telnet option  
CURLE_OBSOLETE,                /* 50 - NOT USED */                            50:    unknown error  
CURLE_SSL_PEER_CERTIFICATE,    /* 51 - peer's certificate wasn't ok */        51:    SSL peer certificate was not ok  
CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */       52:    server returned nothing (no headers, no data)  
CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */         53:    SSL crypto engine not found  
CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as       54:    can not set SSL crypto engine as default  
default */    
CURLE_SEND_ERROR,              /* 55 - failed sending network data */         55:    failed sending data to the peer 
CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */   56:    failure when receiving data from the peer  
CURLE_SHARE_IN_USE,            /* 57 - share is in use */                     57:    share is already in use  
CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */  58:    problem with the local SSL certificate  
CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */       59:    couldn't use specified SSL cipher  
CURLE_SSL_CACERT,              /* 60 - problem with the CA cert (path?) */    60:    peer certificate cannot be authenticated with known CA certificates  
CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized transfer encoding */      61:    Unrecognized HTTP Content-Encoding  
CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */                    62:    Invalid LDAP URL  
CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */          63:    Maximum file size exceeded  
CURLE_FTP_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */      64:    Requested FTP SSL level failed  
CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind     65:    Send failed since rewinding of the data stream failed  
that failed */    
CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */         66:    failed to initialise SSL crypto engine  
CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not      67:    FTP: login denied  
accepted and we failed to login */    
CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */            68:    TFTP: File Not Found  
CURLE_TFTP_PERM,               /* 69 - permission problem on server */        69:    TFTP: Access Violation  
CURLE_TFTP_DISKFULL,           /* 70 - out of disk space on server */         70:    TFTP: Disk full or allocation exceeded  
CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */              71:    TFTP: Illegal operation  
CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */                 72:    TFTP: Unknown transfer ID  
CURLE_TFTP_EXISTS,             /* 73 - File already exists */                 73:    TFTP: File already exists  
CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */                        74:    TFTP: No such user  
CURLE_CONV_FAILED,             /* 75 - conversion failed */                   75:    conversion failed  
CURLE_CONV_REQD,               /* 76 - caller must register conversion        76:    caller must register CURLOPT_CONV_ callback options  
callbacks using curl_easy_setopt options    
CURLOPT_CONV_FROM_NETWORK_FUNCTION,    
CURLOPT_CONV_TO_NETWORK_FUNCTION, and    
CURLOPT_CONV_FROM_UTF8_FUNCTION */    
CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing    77:    problem with the SSL CA cert (path? access rights?)  
or wrong format */    
CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */               78:    Remote file not found  
CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat     79:    Error in the SSH layer  
generic so the error message will be of    
interest when this has happened */    
CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL            80:    Failed to shut down the SSL connection
connection */    
0 0
原创粉丝点击