2016-07-21 18 views
1

Wenn eine 10 MB-Datei über HTTP Upload eine einfache Steckdose mit - alles wie erwartet funktioniert:Synchrone HTTPS POST mit Boost-Asio

string filename("c:\\test.zip"); 
long long fileSize = boost::filesystem::file_size(filename); 

//Read file into memory 
FILE * filePointer; 
fopen_s(&filePointer, filename.c_str(), "rb"); 
unique_ptr<unsigned char[]> charArray(new unsigned char[1024*1024*20]); 
fseek(filePointer, 0, SEEK_SET); 
fread_s(charArray.get(), 1024 * 1024 * 20, sizeof(unsigned char), fileSize, filePointer); 

//Setup Socket 
boost::asio::io_service io_service; 
tcp::endpoint ep; 
ep.port(90); 
ep.address(boost::asio::ip::address_v4::from_string("127.0.0.1")); 

shared_ptr<tcp::socket> httpSocket = make_shared<tcp::socket>(io_service); 
httpSocket->connect(ep); 

string PREFIX = "--"; 
//Use GUID as boundary 
string BOUNDARY = boost::uuids::to_string(boost::uuids::random_generator()()); 
string NEWLINE = "\r\n"; 
int NEWLINE_LENGTH = NEWLINE.length(); 

//Calculate length of entire HTTP request - goes into header 
long long lengthOfRequest = 0; 
lengthOfRequest += PREFIX.length() + BOUNDARY.length() + NEWLINE_LENGTH; 
lengthOfRequest += string("Content-Disposition: form-data; name=\"fmChunk\"; filename=\"test.zip\"").length(); 
lengthOfRequest += NEWLINE_LENGTH + NEWLINE_LENGTH; 
lengthOfRequest += fileSize; 
lengthOfRequest += NEWLINE_LENGTH + PREFIX.length() + BOUNDARY.length() + PREFIX.length() + NEWLINE_LENGTH; 

boost::asio::streambuf request; 
std::ostream request_stream(&request); 

request_stream << "POST /filehandler.ashx HTTP/1.1" << NEWLINE; 
request_stream << "Host: localhost" << NEWLINE; // << ":" << port << NEWLINE; 
request_stream << "User-Agent: FilemailDesktop2Cpp" << NEWLINE; 
request_stream << "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" << NEWLINE; 
request_stream << "Accept-Language: nb,no;q=0.8,nn;q=0.6,en-us;q=0.4,en;q=0.2" << NEWLINE; 
request_stream << "Accept-Encoding: gzip;q=0,deflate;q=0" << NEWLINE; //Disables compression 
request_stream << "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7" << NEWLINE; 
request_stream << "Connection: close" << NEWLINE; 
request_stream << "Content-Length: " << lengthOfRequest << NEWLINE; 
request_stream << "Content-Type: multipart/form-data; boundary=" << BOUNDARY << NEWLINE; 
request_stream << NEWLINE; 

request_stream << PREFIX; 
request_stream << BOUNDARY; 
request_stream << NEWLINE; 
request_stream << "Content-Disposition: form-data; name=\"fmChunk\"; filename=\"test.zip\""; 
request_stream << NEWLINE; 
request_stream << NEWLINE; 

auto data = request.data(); 
httpSocket->write_some(buffer(data)); 

//Send Data (Paytload) 
auto bytesSent = 0; 
while (bytesSent < fileSize) 
{ 
    int bytesToSendNow = min(fileSize - bytesSent, 1024 * 100); 
    httpSocket->write_some(boost::asio::buffer(charArray.get() + bytesSent, bytesToSendNow)); 
    bytesSent += bytesToSendNow; 
} 

//Close request 
httpSocket->write_some(boost::asio::buffer(NEWLINE)); 
httpSocket->write_some(boost::asio::buffer(PREFIX)); 
httpSocket->write_some(boost::asio::buffer(BOUNDARY)); 
httpSocket->write_some(boost::asio::buffer(PREFIX)); 
httpSocket->write_some(boost::asio::buffer(NEWLINE)); 

//Read Response 
boost::asio::streambuf response; 
read_until(*httpSocket, response, "\r\n"); 
string strResponse(boost::asio::buffer_cast<const char*>(response.data()), response.size()); 

//Check Response 
if (strResponse.find("200 OK") != string::npos){ 
    cout << "OK"; 
} 
else 
{ 
    BOOST_FAIL("Upload failed"); 
} 

Aber die gleiche Upload tun über HTTPS funktioniert nicht. Ein anderer Port + der Sockelteil ist so ziemlich der ganze Unterschied.

string filename("c:\\test.zip"); 
long long fileSize = boost::filesystem::file_size(filename); 

//Read file into memory 
FILE * filePointer; 
fopen_s(&filePointer, filename.c_str(), "rb"); 
unique_ptr<unsigned char[]> charArray(new unsigned char[1024 * 1024 * 20]); 
fseek(filePointer, 0, SEEK_SET); 
fread_s(charArray.get(), 1024 * 1024 * 20, sizeof(unsigned char), fileSize, filePointer); 

//Setup Socket 
boost::asio::io_service io_service; 
tcp::endpoint ep; 
ep.port(443); 
ep.address(boost::asio::ip::address_v4::from_string("127.0.0.1")); 

boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); 
ssl_socket sslSocket(io_service, ctx); 
sslSocket.lowest_layer().connect(ep); 
sslSocket.set_verify_mode(boost::asio::ssl::verify_none); 
sslSocket.handshake(ssl_socket::client); 


string PREFIX = "--"; 
//Use GUID as boundary 
string BOUNDARY = boost::uuids::to_string(boost::uuids::random_generator()()); 
string NEWLINE = "\r\n"; 
int NEWLINE_LENGTH = NEWLINE.length(); 

//Calculate length of entire HTTP request - goes into header 
long long lengthOfRequest = 0; 
lengthOfRequest += PREFIX.length() + BOUNDARY.length() + NEWLINE_LENGTH; 
lengthOfRequest += string("Content-Disposition: form-data; name=\"fmChunk\"; filename=\"test.zip\"").length(); 
lengthOfRequest += NEWLINE_LENGTH + NEWLINE_LENGTH; 
lengthOfRequest += fileSize; 
lengthOfRequest += NEWLINE_LENGTH + PREFIX.length() + BOUNDARY.length() + PREFIX.length() + NEWLINE_LENGTH; 

boost::asio::streambuf request; 
std::ostream request_stream(&request); 

request_stream << "POST /filehandler.ashx HTTP/1.1" << NEWLINE; 
request_stream << "Host: localhost" << NEWLINE; // << ":" << port << NEWLINE; 
request_stream << "User-Agent: FilemailDesktop2Cpp" << NEWLINE; 
request_stream << "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" << NEWLINE; 
request_stream << "Accept-Language: nb,no;q=0.8,nn;q=0.6,en-us;q=0.4,en;q=0.2" << NEWLINE; 
request_stream << "Accept-Encoding: gzip;q=0,deflate;q=0" << NEWLINE; //Disables compression 
request_stream << "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7" << NEWLINE; 
request_stream << "Connection: close" << NEWLINE; 
request_stream << "Content-Length: " << lengthOfRequest << NEWLINE; 
request_stream << "Content-Type: multipart/form-data; boundary=" << BOUNDARY << NEWLINE; 
request_stream << NEWLINE; 

request_stream << PREFIX; 
request_stream << BOUNDARY; 
request_stream << NEWLINE; 
request_stream << "Content-Disposition: form-data; name=\"fmChunk\"; filename=\"test.zip\""; 
request_stream << NEWLINE; 
request_stream << NEWLINE; 

auto data = request.data(); 
sslSocket.write_some(buffer(data)); 

//Send Data (Paytload) 
auto bytesSent = 0; 
while (bytesSent < fileSize) 
{ 
    int bytesToSendNow = min(fileSize - bytesSent, 1024 * 100); 
    sslSocket.write_some(boost::asio::buffer(charArray.get() + bytesSent, bytesToSendNow)); 
    bytesSent += bytesToSendNow; 
} 

//Close request 
sslSocket.write_some(boost::asio::buffer(NEWLINE)); 
sslSocket.write_some(boost::asio::buffer(PREFIX)); 
sslSocket.write_some(boost::asio::buffer(BOUNDARY)); 
sslSocket.write_some(boost::asio::buffer(PREFIX)); 
sslSocket.write_some(boost::asio::buffer(NEWLINE)); 


//Read Response 
boost::asio::streambuf response; 
read_until(sslSocket, response, "\r\n"); 
string strResponse(boost::asio::buffer_cast<const char*>(response.data()), response.size()); 

//Check Response 
if (strResponse.find("200 OK") != string::npos){ 
    cout << "OK"; 
} 
else 
{ 
    BOOST_FAIL("Upload failed"); 
} 

Bei der Ausführung dieses Codes, die Upload-Stände auf

read_until(*sslSocket, response, "\r\n"); 

Wenn ich den Prozess dann töten - der Socket geschlossen ist - und das IIS Express Webserver (wo ich auch einen Debugger angeschlossen haben) empfängt die Anfrage und verarbeitet sie. Die Länge der vom Server empfangenen hochgeladenen Datei beträgt immer 1772261 Bytes.

Beim Versuch, eine 1 MB-Datei hochladen - das gleiche passiert, Server erhält nur 180224 Bytes.

Ich bin in der Lage, HTTPS GET-Anfragen mit ähnlichen SSL-Socket-Code machen - und einfache HTTP POST funktioniert auch gut - so scheint es die Kombination von SSL und POST, die einige Probleme für mich schafft.

Gibt es einen internen Puffer/Stream-Limit für sslSockets in Boost?

Würde mich freuen, wenn jemand etwas Licht darauf werfen könnte.

+1

Ihr Beispiel ist wahrscheinlich falsch kopiert. Es gibt keinen Code, der 'sslSocket' in Ihrer Frage verwendet. – sehe

+0

Unterdessen können https://stackoverflow.com/questions/21683142/boostasio-ssl-connection-problems/21730448#21730448 und https://stackoverflow.com/a/21730448/85371 hilfreich sein – sehe

Antwort

0

Vor allem - Entschuldigung den Copy/Paste-Fehler. Es wurde jetzt korrigiert.

Anyways - es stellte sich heraus, das Problem war, dass ich (1024 * 100) Bytes zu Socket jedes Mal schrieb - und das war zu viel für die sslSocket - während es für den httpSocket funktionierte. Reduzieren Sie es auf nur 1024 das Problem behoben.

Ich hätte wirklich den Rückgabewert der sslSocket.write_some Methode überprüft, um sicherzustellen, dass die erwartete Anzahl von Bytes geschrieben wurde.

enter image description here