Sandra Schreiner
2016-02-04 18:01:33 UTC
Dear asio-experts,
I need an advice on the following problem. After a fashion I managed to get this read and write in separate threads (almost) working. The first message is transmitted from client to server without problems. But if I try to send data again, the wrong data is received on server side. On client side everything is fine. Anyway in the session the header fetched by async_read contains random data, the length for the content is therefore wrong and the session get's stuck on the synchronous read afterwards.
It seems impossible that two writes are executed at the same time on client-side, because the send is synchronous, there are no other sending threads and the next send ist called when the result was received from the session.
I tried to figure out what is happening with wireshark, but because the connection is encrypted (SSL) I don't see anything usefull.
I can see that for every [PSH, ACK] and [ACK] there is a [TCP Retransmission] and [TCP Dup ACK]. But nothing is received twice on client/server side.
Any idea what might cause this problem? Any hints what I can do to figure it out by myself?
Maybe I'm doing something essentially wrong. So here is my source code:
Session
-----------------------------------------
void Session::read(){
mTmpBuffer = new char[HEADER_LENGTH];
asio::async_read(mSocket,
asio::buffer(mTmpBuffer, HEADER_LENGTH),
std::bind(&Session::readCallback, this,
std::placeholders::_1, std::placeholders::_2));
}
void Session::readCallback(const asio::error_code& headerError,
size_t bytes_transferred){
if(bytes_transferred != HEADER_LENGTH){
mLogger.log(AbstractLogger::Severity::Warning, "%s %s",
"Session::readCallback wrong size of data packet.", headerError.message().c_str());
closeSession();
}
else{
mReceiveHeader = std::string(mTmpBuffer, HEADER_LENGTH);
delete [] mTmpBuffer;
mTmpBuffer = nullptr;
if(!headerError && decodeHeader(mReceiveHeader, mReceiveMessageLength)){
mTmpBuffer = new char[mReceiveMessageLength];
asio::error_code contentError;
try{
size_t receivedContentLength = asio::read(mSocket, asio::buffer(mTmpBuffer, mReceiveMessageLength),
asio::transfer_all(), contentError);
if(contentError || mReceiveMessageLength != receivedContentLength){
closeSession();
}
else{
mReceiveMessage = std::string(mTmpBuffer, mReceiveMessageLength);
delete [] mTmpBuffer;
mTmpBuffer = nullptr;
std::string msg("thank you");
std::string response;
encodeHeader(msg, response);
write(response);
}
}catch(...){
mLogger.log(AbstractLogger::Severity::Debug, "%s %s",
"Session::readCallback","Something stange happened");
}
}
else{
closeSession();
}
}
}
Client (read thread ist startet after handshake)
----------------------------------
AbstractTLSConnector::ErrorCode Client::handshake(){
asio::error_code err;
mSocket->handshake(asio::ssl::stream_base::client, err);
if(!err){
mConnectionStatus = ConnectionStatus::OPEN;
mReadThread.reset(new std::thread{[this](){
mIoService.reset();
read();
mIoService.run(); }});
return ErrorCode::None;
}
else{
disconnect();
return ErrorCode::HandshakeFailed;
}
}
void Client::read(){
mTmpBuffer = new char[HEADER_LENGTH];
asio::async_read((*mSocket),
asio::buffer(mTmpBuffer, HEADER_LENGTH),
std::bind(&Client::readContent, this,
std::placeholders::_1, std::placeholders::_2));
}
void Client::readContent(const asio::error_code& error,
size_t bytes_transferred){
mReceiveHeader = std::string(mTmpBuffer, HEADER_LENGTH);
delete mTmpBuffer;
mTmpBuffer = nullptr;
if(!error && bytes_transferred == HEADER_LENGTH
&& decodeHeader(mReceiveHeader, mReceiveMessageLength)){
mTmpBuffer = new char[mReceiveMessageLength];
bytes_transferred = asio::read((*mSocket),
asio::buffer(mTmpBuffer, mReceiveMessageLength));
mReceiveMessage = std::string(mTmpBuffer, mReceiveMessageLength);
delete mTmpBuffer;
mTmpBuffer = nullptr;
if (!error && bytes_transferred == mReceiveMessageLength){
mListener.receivedResponse(mReceiveMessage, ErrorCode::None);
read();
}
else{
disconnect();
mListener.receivedResponse("", ErrorCode::ReadFailed);
}
}
else{
disconnect();
mListener.receivedResponse("", ErrorCode::ReadFailed);
}
}
AbstractTLSConnector::ErrorCode Client::send(const std::string& sendData){
if(mConnectionStatus == ConnectionStatus::OPEN){
encodeHeader(sendData, mSendMessage);
size_t dataLength = mSendMessage.size();
asio::error_code err;
size_t bytes_transferred = asio::write((*mSocket),
asio::buffer(mSendMessage, dataLength),
err);
if(!err && bytes_transferred == dataLength) {
return ErrorCode::None;
}
else {
disconnect();
return ErrorCode::WriteFailed;
}
}
else{
return ErrorCode::ConnectionAlreadyClosed;
}
}
Best regards,
Sandra
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
I need an advice on the following problem. After a fashion I managed to get this read and write in separate threads (almost) working. The first message is transmitted from client to server without problems. But if I try to send data again, the wrong data is received on server side. On client side everything is fine. Anyway in the session the header fetched by async_read contains random data, the length for the content is therefore wrong and the session get's stuck on the synchronous read afterwards.
It seems impossible that two writes are executed at the same time on client-side, because the send is synchronous, there are no other sending threads and the next send ist called when the result was received from the session.
I tried to figure out what is happening with wireshark, but because the connection is encrypted (SSL) I don't see anything usefull.
I can see that for every [PSH, ACK] and [ACK] there is a [TCP Retransmission] and [TCP Dup ACK]. But nothing is received twice on client/server side.
Any idea what might cause this problem? Any hints what I can do to figure it out by myself?
Maybe I'm doing something essentially wrong. So here is my source code:
Session
-----------------------------------------
void Session::read(){
mTmpBuffer = new char[HEADER_LENGTH];
asio::async_read(mSocket,
asio::buffer(mTmpBuffer, HEADER_LENGTH),
std::bind(&Session::readCallback, this,
std::placeholders::_1, std::placeholders::_2));
}
void Session::readCallback(const asio::error_code& headerError,
size_t bytes_transferred){
if(bytes_transferred != HEADER_LENGTH){
mLogger.log(AbstractLogger::Severity::Warning, "%s %s",
"Session::readCallback wrong size of data packet.", headerError.message().c_str());
closeSession();
}
else{
mReceiveHeader = std::string(mTmpBuffer, HEADER_LENGTH);
delete [] mTmpBuffer;
mTmpBuffer = nullptr;
if(!headerError && decodeHeader(mReceiveHeader, mReceiveMessageLength)){
mTmpBuffer = new char[mReceiveMessageLength];
asio::error_code contentError;
try{
size_t receivedContentLength = asio::read(mSocket, asio::buffer(mTmpBuffer, mReceiveMessageLength),
asio::transfer_all(), contentError);
if(contentError || mReceiveMessageLength != receivedContentLength){
closeSession();
}
else{
mReceiveMessage = std::string(mTmpBuffer, mReceiveMessageLength);
delete [] mTmpBuffer;
mTmpBuffer = nullptr;
std::string msg("thank you");
std::string response;
encodeHeader(msg, response);
write(response);
}
}catch(...){
mLogger.log(AbstractLogger::Severity::Debug, "%s %s",
"Session::readCallback","Something stange happened");
}
}
else{
closeSession();
}
}
}
Client (read thread ist startet after handshake)
----------------------------------
AbstractTLSConnector::ErrorCode Client::handshake(){
asio::error_code err;
mSocket->handshake(asio::ssl::stream_base::client, err);
if(!err){
mConnectionStatus = ConnectionStatus::OPEN;
mReadThread.reset(new std::thread{[this](){
mIoService.reset();
read();
mIoService.run(); }});
return ErrorCode::None;
}
else{
disconnect();
return ErrorCode::HandshakeFailed;
}
}
void Client::read(){
mTmpBuffer = new char[HEADER_LENGTH];
asio::async_read((*mSocket),
asio::buffer(mTmpBuffer, HEADER_LENGTH),
std::bind(&Client::readContent, this,
std::placeholders::_1, std::placeholders::_2));
}
void Client::readContent(const asio::error_code& error,
size_t bytes_transferred){
mReceiveHeader = std::string(mTmpBuffer, HEADER_LENGTH);
delete mTmpBuffer;
mTmpBuffer = nullptr;
if(!error && bytes_transferred == HEADER_LENGTH
&& decodeHeader(mReceiveHeader, mReceiveMessageLength)){
mTmpBuffer = new char[mReceiveMessageLength];
bytes_transferred = asio::read((*mSocket),
asio::buffer(mTmpBuffer, mReceiveMessageLength));
mReceiveMessage = std::string(mTmpBuffer, mReceiveMessageLength);
delete mTmpBuffer;
mTmpBuffer = nullptr;
if (!error && bytes_transferred == mReceiveMessageLength){
mListener.receivedResponse(mReceiveMessage, ErrorCode::None);
read();
}
else{
disconnect();
mListener.receivedResponse("", ErrorCode::ReadFailed);
}
}
else{
disconnect();
mListener.receivedResponse("", ErrorCode::ReadFailed);
}
}
AbstractTLSConnector::ErrorCode Client::send(const std::string& sendData){
if(mConnectionStatus == ConnectionStatus::OPEN){
encodeHeader(sendData, mSendMessage);
size_t dataLength = mSendMessage.size();
asio::error_code err;
size_t bytes_transferred = asio::write((*mSocket),
asio::buffer(mSendMessage, dataLength),
err);
if(!err && bytes_transferred == dataLength) {
return ErrorCode::None;
}
else {
disconnect();
return ErrorCode::WriteFailed;
}
}
else{
return ErrorCode::ConnectionAlreadyClosed;
}
}
Best regards,
Sandra
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio