问题
I have a class called NIUserSession
which handles a SSL-encrypted connection with a client. This is it, although I removed everything which is not relevant for my question:
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
class NIUserSession
{
public:
/*....*/
void readUntil(std::string until);
/*....*/
private:
/*....*/
void readHandler(const boost::system::error_code& error, std::size_t bytes_transferred);
ssl_socket socket_;
boost::asio::streambuf readBuffer;
/*....*/
};
void NIUserSession::readUntil(std::string until)
{
boost::asio::async_read_until(this->socket_, this->readBuffer, until, boost::bind(&NIUserSession::readHandler,
this,
boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
}
void NIUserSession::readHandler(const boost::system::error_code &error, std::size_t bytes_transferred)
{
if(!error)
{
std::cout << "Bytes transfered: " << bytes_transferred << std::endl;
this->readBuffer.commit(bytes_transferred);
std::istream istrm(&this->readBuffer);
std::string message;
istrm >> message;
std::cout << "Message: " << message << std::endl;
} else {
// ...
}
}
Now a client connects, ssl handshake, etc., and then this line is executed from within NIUserSession
:
this->readUntil("<EOF>");
The server should now wait until the client sends a message and ends it with <EOF>
.
From my client application, I send the following (JSON) data:
The server outputs:
Bytes transfered: 169
Message: {
As you can see, 169 bytes are transfered but only 1 character appears in the output. I think I am doing something wrong with the boost::asio::streambuf
(I never used it before).
回答1:
This line:
istrm >> message;
reads a string delimited by whitespace from the stream. That first "{" is a string delimited by whitespace. You just need to keep reading from istrm
.
Instead of using operator>>
, you can copy the indicated number of bytes to a string by using boost::asio::buffers_begin() to get a random access iterator, and then constructing the string with two iterators. That would look something like this (untested):
const auto bufferIterator = boost::asio::buffers_begin(this->readBuffer.data());
const std::string message(bufferIterator, bufferIterator + bytes_transferred);
this->readBuffer.consume(bytes_transferred);
来源:https://stackoverflow.com/questions/38028766/boost-asio-reading-input-from-ssl-socket-results-in-incomplete-data