用到的库:
其中,boost 库用作编码转换(当然了如果你不转换编码我也拦不了你…)
这个样例不仅有 get / post 操作,我还扔进去了
/* * Network.h * * Created on: 2017年1月19日 * Author: Junyi */
#include
#include
#include
#include
#include
using namespace std;
class Network {
public:
int getinmemory();
vector<string> split(string str, string pattern);
wstring string2wstring(const string str);
string wstring2string(const wstring str);
wstring findText(const wstring origin, const wstring find1, const wstring find2);
string urlEncode(const string& str);
string urlDecode(const string& str);
time_t getTimeStamp();
string mergeCookies(string cookies1, string cookies2);
int get(const string url_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_);
int post(const string url_, const string postData_, const string cookies_, string & cookiesRecv, curl_slist * headers_, wstring & recvData_);
Network();
virtual ~Network();
private:
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;
mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) {
/* out of memory! */
spsc_queue_for_debug.push("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;
}
};
/* * Network.cpp * * Created on: 2017年1月19日 * Author: Junyi */
#include
#include
#include
#include
#include
#include
#include
#include "Network.h"
using namespace std;
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm ;
stm << n ;
return stm.str() ;
}
}
unsigned char toHex(unsigned char x)
{
return x > 9 ? x + 55 : x + 48;
}
unsigned char fromHex(unsigned char x)
{
unsigned char y;
if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
else if (x >= '0' && x <= '9') y = x - '0';
else assert(0);
return y;
}
time_t Network::getTimeStamp()
{//获取10位的时间戳
time_t t = time(0); // t is an integer type
return t;
}
string Network::urlEncode(const string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++)
{
if (isalnum((unsigned char)str[i]) ||
(str[i] == '-') ||
(str[i] == '_') ||
(str[i] == '.') ||
(str[i] == '~'))
strTemp += str[i];
else if (str[i] == ' ')
strTemp += "+";
else
{
strTemp += '%';
strTemp += toHex((unsigned char)str[i] >> 4);
strTemp += toHex((unsigned char)str[i] % 16);
}
}
return strTemp;
}
string Network::urlDecode(const string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++)
{
if (str[i] == '+') strTemp += ' ';
else if (str[i] == '%')
{
assert(i + 2 < length);
unsigned char high = fromHex((unsigned char)str[++i]);
unsigned char low = fromHex((unsigned char)str[++i]);
strTemp += high * 16 + low;
}
else strTemp += str[i];
}
return strTemp;
}
wstring Network::findText(const wstring origin, const wstring find1, const wstring find2)
{
if (origin.empty())
return L"";
size_t found1, found2;
found1 = origin.find(find1);
if ((int)found1 == 0)
return L"";
found2 = origin.find(find2, found1);
if ((int)found2 == 0)
return L"";
return origin.substr(found1 + find1.length(), found2 - found1 - find1.length());
}
// 需包含locale、string头文件、使用setlocale函数。
/*http://www.cnblogs.com/SunboyL/archive/2013/03/31/stringandwstring.html*/
wstring Network::string2wstring(const string str)
{// string转wstring
unsigned len = str.size() * 2;// 预留字节数
setlocale(LC_CTYPE, ""); //必须调用此函数
wchar_t *p = new wchar_t[len];// 申请一段内存存放转换后的字符串
mbstowcs(p, str.c_str(), len);// 转换
wstring str1(p);
delete[] p;// 释放申请的内存
return str1;
}
string Network::wstring2string(const wstring str)
{// wstring转string
unsigned len = str.size() * 4;
setlocale(LC_CTYPE, "");
char *p = new char[len];
wcstombs(p, str.c_str(), len);
string str1(p);
delete[] p;
return str1;
}
vector<string> Network::split(string str, string pattern)
{
string::size_type pos;
vector<string> result;
str += pattern;//扩展字符串以方便操作
unsigned int size = str.size();
for (unsigned int i = 0; iif (pos < size)
{
string s = str.substr(i, pos - i);
result.push_back(s);
i = pos + pattern.size() - 1;
}
}
return result;
}
int Network::post(const string url_, const string postData_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_)
{
CURL *curl_handle;
CURLcode res;
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_handle = curl_easy_init();
if(curl_handle)
{
curl_easy_setopt(curl_handle, CURLOPT_URL, url_.c_str());
curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postData_.c_str());
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "");/* Start Cookies Engine */
curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies_.c_str());
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers_);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
res = curl_easy_perform(curl_handle);
if (res != CURLE_OK) {
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return -1;
}
else
{
string cookiesResult("");
struct curl_slist *cookiesList = NULL;
struct curl_slist *cookiesList_original = NULL; // 保存一个指针副本
curl_easy_getinfo(curl_handle, CURLINFO_COOKIELIST, &cookiesList);
while(cookiesList)
{
vector<string> s = split(cookiesList->data, "\t");
if(s.size() == 7)
{
cookiesResult.append(s[5]);
cookiesResult.append("=");
cookiesResult.append(s[6]);
cookiesResult.append("; ");
}
cookiesList = cookiesList->next;
}
curl_slist_free_all(cookiesList_original); // 注意!!一定要释放 cookiesList_original !不然会引起内存泄漏
cookiesResult = cookiesResult.substr(0, cookiesResult.size() - 2);
cookiesRecv_ = cookiesResult;
string afterCoding("");
afterCoding = chunk.memory;
afterCoding = boost::locale::conv::from_utf(afterCoding, "GBK");
recvData_ = string2wstring(afterCoding);
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return 0;
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return -2;
}
int Network::get(const string url_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_)
{
CURL *curl_handle;
CURLcode res;
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 */
/* init the curl session */
curl_handle = curl_easy_init();
if(curl_handle)
{
curl_easy_setopt(curl_handle, CURLOPT_URL, url_.c_str());
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "");/* Start Cookies Engine */
curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies_.c_str());
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers_);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
res = curl_easy_perform(curl_handle);
if (res != CURLE_OK) {
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return -1;
}
else
{
string cookiesResult("");
struct curl_slist *cookiesList = NULL;
struct curl_slist *cookiesList_original = NULL;
curl_easy_getinfo(curl_handle, CURLINFO_COOKIELIST, &cookiesList);
cookiesList_original = cookiesList;
while(cookiesList)
{
vector<string> s = split(cookiesList->data, "\t");
if(s.size() == 7)
{
cookiesResult.append(s[5]);
cookiesResult.append("=");
cookiesResult.append(s[6]);
cookiesResult.append("; ");
}
cookiesList = cookiesList->next;
}
curl_slist_free_all(cookiesList_original); // 注意!!一定要释放!不然会引起内存泄漏
cookiesResult = cookiesResult.substr(0, cookiesResult.size() - 2);
cookiesRecv_ = cookiesResult;
string afterCoding("");
afterCoding = chunk.memory;
afterCoding = boost::locale::conv::from_utf(afterCoding, "GBK");
recvData_ = string2wstring(afterCoding);
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return 0;
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
return -2;
}
void mapInsert(map<string, string> &m, string first, string second)
{
map<string, string>::iterator it;
it = m.find(first);
if (it == m.end())
m.insert(pair<string, string>(first, second));
else
it->second = second;
}
string Network::mergeCookies(string cookies1, string cookies2)
{
using namespace boost;
map<string, string> m;//result cookies
erase_all(cookies1, " ");
erase_all(cookies2, " ");
vector<string> s1 = split(cookies1, ";");
vector<string> s2 = split(cookies2, ";");
for (vector<string>::iterator it = s1.begin(); it != s1.end(); it++)
{
vector<string> s11 = split((*it), "=");
if (s11.size() != 2)
continue;
mapInsert(m, s11[0], s11[1]);
}
for (vector<string>::iterator it = s2.begin(); it != s2.end(); it++)
{
vector<string> s22 = split((*it), "=");
if (s22.size() != 2)
continue;
mapInsert(m, s22[0], s22[1]);
}
string result("");
for (map<string, string>::iterator it = m.begin(); it != m.end(); it++)
{
result.append(it->first);
result.append("=");
result.append(it->second);
result.append("; ");
}
result = result.substr(0, result.size() - 2);//去掉最后多余的的 [; ]
return result;
}
Network::Network() {
}
Network::~Network() {
}
#include
#include "Network.h"
int main()
{
Network nt;
string cookiesRecv("");
wstring getRecv(L"");
curl_slist *headers = NULL;
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36");
headers = curl_slist_append(headers, "Accept: application/json, text/javascript, */*; q=0.01");
headers = curl_slist_append(headers, "Connection: Keep-Alive");
headers = curl_slist_append(headers, "Pragma: no-cache");
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded; charset=UTF-8");
nt.get("http://www.baidu.com", "", cookiesRecv, headers, getRecv);
curl_slist_free_all(headers); // 用完就释放!
std::cout << nt.wstring2string(getRecv) << std::endl;
return 0;
}
g++ main.cpp Network.cpp Network.h -o main -lcurl -lcurldll -lboost_locale-mgw53-mt-1_62
(注意:-lcurldll 和 -lboost_locale-mgw53-mt-1_62 根据个人情况而定!)
(linux下如果安装了 libcurl4-openssl-dev 和 libboost-dev,编译命令为:g++ main.cpp Network.cpp Network.h -o main -lcurl -lboost_locale
)
(编译环境:MinGW gcc-5.3.0 在各种库都配置正常的情况下,本篇文章编译通过并能正常使用)
附言:
C++新人一个,如代码有问题欢迎评论指出!