1.CURL几个基本函数的说明:
1) curl_global_init();这个函数是进行curl库的初始化,这个函数与curl_global_cleanup配套使用,当调用了一次后,在没有调用curl_global_cleanup之前不要再次调用。
2) curl_global_cleanup();对curl_global_init进行的一些操作进行清理。
3) CURL *curl_easy_init( );用于产生一个CURL对象用于进行网络相关的操作,此对象类似于文件指针,不使用它的时候需要进行清理释放。
4) void curl_easy_cleanup(CURL *curl);用于对CURL*的清理释放。
5) void curl_easy_reset(CURL *handle );重新初始化CURL句柄的选项设置。
6) CURLcode curl_easy_getinfo(CURL *curl,CURLINFO info, ... );查询CRUL会话的内部信息,具体说明请参考curl自带文档。
7.) CURLcode curl_easy_setopt(CURL *curl,CURLoption option, ...);此函数是curl中最核心的函数,基本所有的网络操作的设定都需要它去进行,他的参数等也非常的复杂,建议自行搜索这个函数相关的内容。
8) CURLcode curl_easy_perform(CURL *curl);针对curl_easy_setopt设置好的内容参数进行相应的网络操作。
2.CURL库在android JNI中的具体使用(HTTP请求和文件下载):
创建android工程以后需要在AndroidManifest.xml文件中添加使用权限:
使用curl封装的一个简单的http请求类HttpPostModule
HttpPostModule.h
#ifndef HTTP_POST_MODULE_H
#define HTTP_POST_MODULE_H
#include
#include "curl/curl.h"
#include
using namespace std;
typedef size_t (*WriteFunc)(char *ptr, size_t size, size_t nmemb,
void *userdata);
/*
* 发送http请求
* 使用开源curl库进行相应的实现
* */
class HttpPostModule
{
public:
HttpPostModule();
virtual ~HttpPostModule();
static void Init();
static void Cleanup();
public:
//设置超时
bool SetTimeOut(unsigned short usSecond);
//设置 请求的url
bool SetURL(const string& strURL);
//设置http头
bool SetHttpHead(const string& strHttpHead);
//设置返回数据回调函数
bool SetWriteFunction(WriteFunc pFunc);
//发送http请求
int SendPostRequest(void);
private:
CURL* m_pCurl;
public:
};
//NetModule end
#endif
HttpPostModule.cpp
#include "HttpPostModule.h"
HttpPostModule::HttpPostModule() :
m_pCurl(NULL)
{
m_pCurl = curl_easy_init();
curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);
}
HttpPostModule::~HttpPostModule()
{
curl_easy_cleanup(m_pCurl);
m_pCurl = NULL;
}
void HttpPostModule::Init()
{
curl_global_init(CURL_GLOBAL_ALL);
}
void HttpPostModule::Cleanup()
{
curl_global_cleanup();
}
bool HttpPostModule::SetTimeOut(unsigned short usSecond)
{
if (m_pCurl == NULL)
return false;
int nRet = curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, usSecond);
if (nRet == CURLE_OK)
return true;
else
{
cout << "SetTimeOut ERROR code =" << nRet << endl;
return false;
}
}
bool HttpPostModule::SetURL(const string& strURL)
{
if (m_pCurl == NULL)
return false;
int nRet = curl_easy_setopt(m_pCurl, CURLOPT_URL, strURL.c_str());
if (nRet == CURLE_OK)
return true;
else
{
cout << "SetURL ERROR code =" << nRet << endl;
return false;
}
}
bool HttpPostModule::SetHttpHead(const string& strHttpHead)
{
if (m_pCurl == NULL)
return false;
curl_slist *plist = curl_slist_append(NULL, strHttpHead.c_str());
int nRet = curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, plist);
if (nRet == CURLE_OK)
return true;
else
{
cout << "SetHttpHead ERROR code =" << nRet << endl;
return false;
}
}
bool HttpPostModule::SetWriteFunction(WriteFunc pFunc)
{
if (m_pCurl == NULL)
return false;
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, NULL);
int nRet = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, pFunc);
if (nRet == CURLE_OK)
return true;
else
{
cout << "SetCallbackFunc ERROR code =" << nRet << endl;
return false;
}
}
int HttpPostModule::SendPostRequest(void)
{
if (m_pCurl == NULL)
return -1;
int nRet = curl_easy_perform(m_pCurl);
if (nRet == CURLE_OK)
return 0;
else
{
return nRet;
}
}
使用curl封装的一个简单的文件下载类DownloadModule,文件下载支持断点续传。
DownloadModule.h
#ifndef DOWNLOAD_MODULE_H
#define DOWNLOAD_MODULE_H
#include
#include "curl/curl.h"
using namespace std;
class DownLoadModule
{
public:
DownLoadModule();
virtual ~DownLoadModule();
static void Init();
static void Cleanup();
public:
static size_t DownLoadPackage(void *ptr, size_t size, size_t nmemb,
void *userdata);
private:
long GetLocalFileLenth(const string& strFileName);
public:
/*
* param1 string 下载文件的url地址。
* param2 string 下载到的路径 注意要以/结尾
* param3 string 下载后的文件名
* return 0 下载成功/-1代表初始化失败/其他为curl返回错误码
* */
int DownLoad(std::string strUrl, std::string strStoragePath,
std::string strFileName);
private:
CURL *m_pCurl;
};
#endif
#include
#include
#include "DownloadModule.h"
DownLoadModule::DownLoadModule() :
m_pCurl(NULL)
{
m_pCurl = curl_easy_init();
}
DownLoadModule::~DownLoadModule()
{
curl_easy_cleanup(m_pCurl);
m_pCurl = NULL;
}
void DownLoadModule::Init()
{
curl_global_init(CURL_GLOBAL_ALL);
}
void DownLoadModule::Cleanup()
{
curl_global_cleanup();
}
size_t DownLoadModule::DownLoadPackage(void *ptr, size_t size, size_t nmemb,
void *userdata)
{
FILE *fp = (FILE*) userdata;
size_t written = fwrite(ptr, size, nmemb, fp);
return written;
}
long DownLoadModule::GetLocalFileLenth(const string& strFileName)
{
unsigned long filesize = 0;
struct stat statbuff;
if (stat(strFileName.c_str(), &statbuff) < 0)
{
return filesize;
}
else
{
filesize = statbuff.st_size;
}
return filesize;
}
int DownLoadModule::DownLoad(std::string strUrl, std::string strStoragePath,
std::string strFileName)
{
Init();
// Create a file to save package.
if (0 != access(strStoragePath.c_str(), F_OK))
mkdir(strStoragePath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
;
const string outFileName = strStoragePath + "/" + strFileName;
//================断点续载===================
long localLen = GetLocalFileLenth(outFileName.c_str());
FILE *fp = fopen(outFileName.c_str(), "a+b");
if (!fp)
{
return -1;
}
fseek(fp, 0, SEEK_END);
// Download pacakge
CURLcode res;
curl_easy_setopt(m_pCurl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, DownLoadPackage);
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, true);
//curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, 30);
curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(m_pCurl, CURLOPT_HEADER, 0L);
curl_easy_setopt(m_pCurl, CURLOPT_NOBODY, 0L);
curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM, localLen);
res = curl_easy_perform(m_pCurl);
Cleanup();
if (res != 0)
{
fclose(fp);
return res;
}
fclose(fp);
return 0;
}
具体功能实现:下载一个APK文件和发送一个百度地图API的Http请求。
java端代码 MainActivity.class
package com.example.curltest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
static {
System.loadLibrary("curl");
System.loadLibrary("curlTest");
}
public native void Init();
public native void Cleanup();
public native void TestDownload();
public native void TestHttpPost();
private final String TAG = "curlTest";
private void postDispose(String Data)
{
Log.i(TAG, Data);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Init();
Button btnPost = (Button) findViewById(R.id.main_post);
Button btnDownload = (Button) findViewById(R.id.main_download);
btnPost.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
TestHttpPost();
}
});
btnDownload.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
TestDownload();
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Cleanup();
}
}
JNI代码Main.cpp
#include
#include "DownloadModule.h"
#include "HttpPostModule.h"
#include "JNIUtil.h"
extern "C"
{
jobject g_objAc = NULL;
void Java_com_example_curltest_MainActivity_TestDownload(JNIEnv* env,
jobject obj)
{
DownLoadModule download;
const char* url =
"http://s3.amazonaws.com/hum9-lwg8-qa2w/PsiphonAndroid.apk";
int nRet = download.DownLoad(url, "/sdcard/Download", "PsiphonAndroid.apk");
if (nRet == 0)
LOGI("download success!");
else
LOGE("download error code:%d", nRet);
}
size_t PostDispose(char *buffer, size_t size, size_t nmemb, void *userdata)
{
JNIUtil util;
jobject jdata = util.String2Jstring(buffer);
JNIEnv* env = util.GetJNIEnv();
jclass cMainActivity = env->GetObjectClass(g_objAc);
jmethodID methodPostDispose = env->GetMethodID(cMainActivity, "postDispose",
"(Ljava/lang/String;)V");
env->CallVoidMethod(g_objAc, methodPostDispose, jdata);
return nmemb;
}
void Java_com_example_curltest_MainActivity_TestHttpPost(JNIEnv* env,
jobject obj)
{
HttpPostModule post;
post.SetTimeOut(60);
post.SetHttpHead("Content-Type:application/json;charset=UTF-8");
post.SetWriteFunction(PostDispose);
post.SetURL("http://api.map.baidu.com/place/v2/suggestion?query=tiananmen®ion=131&output=json&ak=fTF5Wt01MNLs7ci9G9G6X76d");
int nRet = post.SendPostRequest();
if (nRet == 0)
LOGI("post success!");
else
LOGE("post error code:%d", nRet);
}
void Java_com_example_curltest_MainActivity_Init(JNIEnv* env, jobject obj)
{
HttpPostModule::Init();
JavaVM* vm;
env->GetJavaVM(&vm);
JNIUtil::Init(env);
g_objAc = env->NewGlobalRef(obj);
}
void Java_com_example_curltest_MainActivity_Cleanup(JNIEnv* env, jobject obj)
{
HttpPostModule::Cleanup();
env->DeleteGlobalRef(g_objAc);
g_objAc = NULL;
JNIUtil::CleanUp(env);
}
}
里面的JNIUtil工具类在我的另一篇博客有详细说明。
http://blog.csdn.net/csdn49532/article/details/50635338
整个项目工程源码:
http://download.csdn.net/detail/csdn49532/9434453