【发布时间】:2016-07-21 21:23:26
【问题描述】:
使用普通套接字通过 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 是否存在内部缓冲区/流限制?
如果有人能对此有所了解,将不胜感激。
【问题讨论】:
-
您的样本可能未复制粘贴。在您的问题中根本没有使用
sslSocket的代码。
标签: c++ sockets http boost boost-asio