multiThreadQuery.h:
#ifndef MULTITHREADQUERY_H
#define MULTITHREADQUERY_H
#endif
#include <vector>
#include <string>
using namespace std;
class multiThreadQuery{
public:
explicit multiThreadQuery();
~multiThreadQuery();
multiThreadQuery* clearAllUrls();
multiThreadQuery* attachUrl(std::string url, std::string alias = "", std::string cookie = "", std::string userAgent = "");
multiThreadQuery* fetchResponse(bool yesNo);
std::string exe();
protected:
int _threadNum;
vector
bool _fetchResponse;
void _curl(int i);
vector
};
multiThreadQuery.cpp:
#include "multiThreadQuery.h"
#include "/usr/include/Poco/Net/HTTPClientSession.h"
#include "/usr/include/Poco/Net/HTTPRequest.h"
#include "/usr/include/Poco/Net/HTTPResponse.h"
#include "/usr/include/Poco/StreamCopier.h"
#include "/usr/include/Poco/Path.h"
#include "/usr/include/Poco/URI.h"
#include "/usr/include/Poco/Exception.h"
#include <iostream>
#include <thread>
#include <cstdlib>
#include <sstream>
#include <utility>
#include <chrono>
using namespace std;
using namespace Poco;
using namespace Poco::Net;
multiThreadQuery::multiThreadQuery(void): _threadNum(0), _fetchResponse(false){
}
multiThreadQuery::~multiThreadQuery(void){
}
multiThreadQuery* multiThreadQuery::clearAllUrls(){
_threadNum = 0;
vector
_urlContainer = emptyContainer;
_aliasContainer = emptyContainer;
_cookieContainer = emptyContainer;
_userAgentContainer = emptyContainer;
_responseContainer = emptyContainer;
return this;
}
multiThreadQuery* multiThreadQuery::attachUrl(std::string url, std::string alias, std::string cookie, std::string userAgent){
_urlContainer.push_back(url);
if(alias != ""){
_aliasContainer.push_back(alias);
}else{
// time_point的time_since_epoch()才會包含小數點
chrono::system_clock::time_point tp = chrono::system_clock::now();
chrono::microseconds us = chrono::duration_cast
time_t tt = us.count();
stringstream strm;
strm << tt;
_aliasContainer.push_back(strm.str());
}
_cookieContainer.push_back(cookie);
_userAgentContainer.push_back(userAgent);
_responseContainer.push_back("");
++_threadNum;
return this;
}
multiThreadQuery* multiThreadQuery::fetchResponse(bool yesNo){
_fetchResponse = yesNo;
return this;
}
std::string multiThreadQuery::exe(){
int i;
std::string json = "";
// 動態設定array大小
thread* threadArrPtr = new thread[_threadNum];
for(i = 0; i < _threadNum; ++i){
*(threadArrPtr + i) = thread(&multiThreadQuery::_curl, this, i);
}
if(_fetchResponse) json = "{";
for(i = 0; i < _threadNum; ++i){
// 不得放在產生thread的迴圈內,多執行緒會失效,變成跑一般迴圈
(*(threadArrPtr + i)).join();
if(_fetchResponse){
json += _responseContainer[i];
if(i != _threadNum - 1) json += ",";
}
}
if(_fetchResponse) json += "}";
delete [] threadArrPtr;
threadArrPtr = nullptr;
return json;
}
void multiThreadQuery::_curl(int i){
try{
URI uri(_urlContainer[i]);
HTTPClientSession session(uri.getHost(), uri.getPort());
// prepare path
string path(uri.getPathAndQuery());
if(path.empty()) path = "/";
// send request
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
if(_cookieContainer[i] != ""){
NameValueCollection nvc;
vector
for(vector
std::string cookieName = (*it).substr(0, (*it).find("="));
std::string cookieValue = (*it).substr((*it).find("=") + 1);
nvc.add(cookieName, cookieValue);
}
req.setCookies(nvc);
}
if(_userAgentContainer[i] != "") req.set("User-Agent", _userAgentContainer[i]);
session.sendRequest(req);
if(_fetchResponse){
HTTPResponse res;
// response 轉成 stream 再轉成字串
istream &is = session.receiveResponse(res);
std::string response;
StreamCopier::copyToString(is, response);
_responseContainer[i] = "\"" + _aliasContainer[i] + "\":" + response;
}
}catch(Poco::Exception &ex){
_responseContainer[i] = "\"" + _aliasContainer[i] + "\":{\"s\":-5,\"desc\":\"Curl '" + _urlContainer[i] + "' failed.\"}";
}
}
vector
std::vector
std::istringstream iss(str);
for(std::string token; getline(iss, token, delimiter);){
result.push_back(move(token));
}
return result;
}
int main(){
const auto start = chrono::system_clock::now();
multiThreadQuery mtq;
std::string response;
response = mtq.clearAllUrls()->fetchResponse(true)
->attachUrl("http://127.0.0.1/test.php", "test", "snm=54659c9a7decb:SMH2IG9QAVAEBFNYMXK3I3NNH6;snm_token=d7d4a58c3d3d69cb32bf74fa84e4f416;", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0")
->attachUrl("http://127.0.0.1/helloWorld.php", "hw", "snm=54659c9a7decb:SMH2IG9QAVAEBFNYMXK3I3NNH6;snm_token=d7d4a58c3d3d69cb32bf74fa84e4f416;", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0")
->exe();
cout << response << endl;
const auto end = chrono::system_clock::now();
auto ts = end - start;
cout << "spent: " << chrono::duration_cast
return 0;
}
至於如何包成PHP的Extension檔,再自行參考前幾篇裡的說明囉~
沒有留言:
張貼留言