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.
Ihr Beispiel ist wahrscheinlich falsch kopiert. Es gibt keinen Code, der 'sslSocket' in Ihrer Frage verwendet. – sehe
Unterdessen können https://stackoverflow.com/questions/21683142/boostasio-ssl-connection-problems/21730448#21730448 und https://stackoverflow.com/a/21730448/85371 hilfreich sein – sehe