使用普通套接字通过HTTP上传10 MB文件时 - 一切都按预期工作:
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");
}
但是通过HTTPS执行相同的上传不起作用。一个不同的端口+插座部分几乎完全不同。
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");
}
运行此代码时,上传会在
处停止read_until(*sslSocket, response, "\r\n");
如果我然后终止进程 - 套接字被关闭 - IIS Express网络服务器(我还附加了一个调试器)接收请求并处理它。服务器接收的上载文件的长度始终为1772261字节。
当尝试上传1MB文件时 - 同样的情况发生,服务器只接收180224个字节。
我能够使用类似的sslSocket代码发出HTTPS GET请求 - 而普通的HTTP POST也可以正常工作 - 所以它似乎是SSL和POST的组合,这给我带来了一些问题。
Boost中的sslSockets是否存在内部缓冲区/流限制?
如果有人能够对此有所了解,我们将不胜感激。