libcurl是一个免费开源的,客户端url传输库,支持FTP,FTPS,TFTP,HTTP,HTTPS等常见协议,跨平台,支持Windows,Unix,Linux等,线程安全,支持Ipv6。并且易于使用的函数库,http://curl.haxx.se/libcurl/

大致的使用方法如下:

    curl = curl_easy_init();//初始化

    if(curl){
        ...
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);//post的字符串
        curl_easy_setopt(curl, CURLOPT_HEADER, 1);//一并获取响应头
        curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");//采用gzip压缩
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(postthis));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);//接收响应数据
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, nsp_reci);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT,CURLTIMEOUT);//超时时间
        res = curl_easy_perform(curl);
        if(CURLE_OK == res) {
            long code;
            curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &code);
            
            if(code != 200){
                ...
                curl_easy_cleanup(curl);
                return false;
            }
            curl_easy_cleanup(curl);return false;}
        }
        curl_easy_cleanup(curl);
    }
其中的write_data函数是用来接收响应的内容的
    size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
    {
        strcat((char *)stream,ptr);
        //strcpy(stream,(char *)ptr);   //使用strcat而不是strcpy

        return size*nmemb;
    }

很多网上的代码都是用的strcpy而不是strcat,这个在网络情况不好的时候会有问题, libcurl中这个数据接收函数会被多次调用,所以需要把数据拼接起来才是完整的响应内容,很多程序例子都忽略了这点。

倘若要上传文件和数据,可简单地参照下面的使用格式

    curl_formadd(&formpost,
                &lastptr,
                CURLFORM_COPYNAME, "file",
                CURLFORM_BUFFER, filename,
                CURLFORM_BUFFERPTR, buffer,
                CURLFORM_BUFFERLENGTH, buffer_len,
                CURLFORM_END);
这里需要注意buffer_len是一个long型数据,而不是int类型,不然在64位机器上运行libcurl的库会出现内存错误。

很多服务器支持gzip数据的传输,下面这个函数可以用于gzip数据的解压缩,测试可用,只是需要注意参数nzdata和ndata都是uLong类型的数据,传递参数时ndata需要是一个最大的uLong数字。

/* HTTP gzip decompress */
/* 参数1.压缩数据 2.数据长度 3.解压数据 4.解压后长度 */
int httpgzdecompress(Byte *zdata, uLong nzdata, Byte *data, uLong *ndata)
{
    int err = 0;
    z_stream d_stream = {0}; /* decompression stream */
    static char dummy_head[2] = 
    {
        0x8 + 0x7 * 0x10,
        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
    };
    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;
    d_stream.next_in  = zdata;
    d_stream.avail_in = 0;
    d_stream.next_out = data;
    if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
    while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) 
    {
        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
        if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
        if(err != Z_OK )
        {
            if(err == Z_DATA_ERROR)
            {
                d_stream.next_in = (Bytef*) dummy_head;
                d_stream.avail_in = sizeof(dummy_head);
                if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 
                {
                    return -1;
                }
            }
            else return -1;
        }
    }
    if(inflateEnd(&d_stream) != Z_OK) return -1;
    *ndata = d_stream.total_out;
    return 0;
} 
使用方法如:
int declen;
httpgzdecompress((Byte *)ptr,size*nmemb,(Byte *)dec,(uLong *)&declen);

其中declen不可赋初值,因为参数转换会产生uLong类型的一个大数,这在解压缩中有用,倘若赋初值0,则解压缩会失败

Logo

更多推荐