웹 서비스를 공격하는 방법을 알아 내고, 동시에 파싱하는 동안 json을 파싱하고 deserialize하는 동안 내 머리카락을 찢어 내고 있습니다. 전체 문서 저장 (500mb +). 효과적으로, 내 클래스에 바로 SAX 스타일 구문 분석을 사용하여 libcurl과 rapidjson을 연결하려고합니다.스트리밍 역 직렬화에 대한 Libcurl + rapidjson?
어쩌면 나는이 잘못에 대해 생각하고있다. 그러나 curl_writeback 중에는 json 텍스트 스트림에 수신 된 데이터를 추가하는 것이 현재의 생각이다. 내가 고민하는 것은 rapidjson 구문 분석 엔진을 시작하고 컬링 쓰기 되돌림에서 오는 데이터 블록을 기다리는 방법입니다. 새로운 스트림 버퍼가 수신 될 때까지 미완료 된 토큰이 처리되기 전에 정지. 이전 버퍼를 비우고 싶기 때문에 버퍼를 추가하고 싶지 않습니다.
이전에이 작업을 수행 한 사람이 있습니까? 여기
몇 가지 개념을 설명하는 코드 ...하지만 분명히 완료되지 않은 (모든 잘못 아마와!) 여기에 가가에 콜백을 수행하는 방법을 알 수 있도록 curl_write 정보를 전달하는 구조입니다 파서.rapidjson::Reader reader;
CurlHandler handler;
ParseHandler parser;
handler.reader = &reader;
handler.parsehandler = &parser;
SetOption(CURLOPT_WRITEDATA, (void *) &handler);
ParseHandler는 SAX 구문 분석을 할 rapidjson가 필요로하는 클래스입니다 다음과 같이
struct CurlHandler {
stringstream *data;
Reader *reader;
void *parsehandler;
};
는 그런 요청을 시작하기 전에, 나는 구조를 채 웁니다. 나는 확실히이보다 쉽게 응답이 희망
static size_t curl_write(void *ptr, size_t size, size_t nmemb, void *CurlHandlerPtr) {
CurlHandler *handler = (CurlHandler *) CurlHandlerPtr;
// handler->reader.Parse(handler->data, handler->parsehandler); ????????
return 1;
}
: 아이디어는 curl_write 동안 rapidjson 파서 (어떻게 든)를 호출하는 것이 었습니다.
#pragma once
#include <string>
#include <iostream>
#include "curl\curl.h"
#include "rapidjson\rapidjson.h"
#include "rapidjson\reader.h"
using namespace std;
using namespace rapidjson;
struct CurlHandler {
stringstream *data;
Reader *reader;
void *parsehandler;
};
static size_t curl_write(void *ptr, size_t size, size_t nmemb, void *CurlHandlerPtr) {
CurlHandler *handler = (CurlHandler *) CurlHandlerPtr;
// handler->reader.Parse(handler->data, handler->parsehandler); ????????
return 1;
}
class ParseHandler {
bool Null() { cout << "Null()" << endl; return true; }
bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; }
bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; }
bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; }
bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; }
bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; }
bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; }
bool String(const char* str, SizeType length, bool copy) {
cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool StartObject() { cout << "StartObject()" << endl; return true; }
bool Key(const char* str, SizeType length, bool copy) {
cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; }
bool StartArray() { cout << "StartArray()" << endl; return true; }
bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; }
};
class StreamTest {
private:
string _username;
string _password;
CURL *_curl;
CURLcode _error;
public:
StreamTest() {
curl_global_init(CURL_GLOBAL_ALL);
_curl = curl_easy_init();
};
~StreamTest() {
curl_global_cleanup();
};
int Initialize(string username, string password) {
_username = username;
_password = password;
return 0;
}
int Get(std::string url) {
CURLcode result;
rapidjson::Reader reader;
CurlHandler handler;
ParseHandler parser;
handler.reader = &reader;
handler.parsehandler = &parser;
std::string s = _username; s += ":"; s += _password;
SetOption(CURLOPT_USERPWD, s.c_str());
SetOption(CURLOPT_URL, url.c_str());
SetOption(CURLOPT_WRITEFUNCTION, curl_write);
SetOption(CURLOPT_WRITEDATA, (void *) &handler);
result = curl_easy_perform(_curl);
return 0;
}
template <typename ValueType>
StreamTest& SetOption(CURLoption opt, ValueType val) {
if(_curl && _error == CURLE_OK) {
_error = curl_easy_setopt(_curl, opt, val);
}
return *this;
}
};
int _tmain(int argc, _TCHAR* argv[]) {
StreamTest http;
http.Initialize("guest", "passwd");
http.Get("http://localhost/GetData");
cin.get();
}
EDIT :
이상적 _tmain http.Get의 함수로 탈 직렬화 될 개체에 대한 참조를 전달 것이다
여기 문맥 전체 코드이다. 객체는 일종의 콜백으로 rapidjson에서 모든 SAX 이벤트를 수신합니다.
마일로, 감사합니다. 그러나 구문 분석 속도는 문제가 아니므로 멀티 스레딩이 필요하지는 않습니다. RapidJson은 빨리 망할 것입니다. 문제는 주로 메모리 소비입니다. 만약 내가하고있는 모든것이 객체로 forward 읽기 전용 파싱이라면 나는 500MB + 파일을 메모리에로드하지 않을 것이다. – user3072517
내 대답에 접근 방식을 사용하면 메모리를 줄일 수 있다고 생각합니다.SAX 인터페이스와 HTTP에서 JSON 스트리밍을 사용하는 한 전체 JSON을 메모리에 저장할 필요는 없습니다. –