sumit kang sumit kang - 15 days ago 6
C++ Question

Boost Client not able to receive message from server

I am new to boost library so need some help in modifying this function to get a return message from server.

if i remove the second portion of the code the server is able to read message from the client.

But when i try to read the return message from the server(code in the second portion) the server gives error "Cannot read from socket"

void send_something(std::string host, int port, std::string message)
{
boost::asio::io_service ios;

boost::asio::ip::tcp::endpoint
endpoint(boost::asio::ip::address::from_string(host), port);
boost::asio::ip::tcp::socket socket(ios);
socket.connect(endpoint);
boost::array<char, 128> buf;
std::copy(message.begin(),message.end(),buf.begin());
boost::system::error_code error;
socket.write_some(boost::asio::buffer(buf, message.size()), error);
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
{
// break;
}// Connection closed cleanly by peer.
else if (error)
{
throw boost::system::system_error(error); // Some other error.
}

std::cout.write(buf.data(), len);
}

Answer

Here is the code that does what you want. Note that, I have not implemented any framing for receiving the data from the server, so it may or may not happen that you receive the complete data.

In case you want to receive the complete message from the server, you can loop around read_some just like how it's done for write_some till your read message size is equal to what you were expecting.

There are other flavours of reading as well like read_until by which you let asio collect the response until it sees the specified pattern for eg an new line('\n' or \r\n).

#include <iostream>
#include <array>
#include <string>
#include <system_error>
#include <asio.hpp>


void send_something(std::string host, int port, std::string message)
{
    asio::io_service ios;

    asio::ip::tcp::endpoint
    endpoint(asio::ip::address::from_string(host), port);
    asio::ip::tcp::socket socket(ios);
    socket.connect(endpoint);

    std::error_code error;
    size_t len = 0;
    // Write the complete message
    while (len < message.length()) {
      len += socket.write_some(asio::buffer(message), error);
    }

    std::array<char, 128> buf;
    socket.read_some(asio::buffer(buf), error);

    if (error == asio::error::eof)
    {
      std::cout << "Connection closed by server\n";
    }
    else if (error)
    {
      std::cout << "ERROR in connection" << std::endl;
      return;
    }

    std::cout << "Received: " << buf.data() << std::endl;
}  


int main() {
  send_something("127.0.0.1", 7869, "Hello!");
  return 0;
}

TEST::

Python 2.7.10 (default, Jul 14 2015, 19:46:27)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket as sock
>>> sd = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
>>> sd
<socket._socketobject object at 0x1088d2c20>
>>> sd.bind(("localhost", 7869))
>>> sd.listen(2)
>>> c, a = sd.accept()
>>> c
<socket._socketobject object at 0x1088d2c90>
>>> buf = c.recv(512)
>>> buf
'Hello!'
>>>
>>> c.send("Cool!")
5

MacBook-Pro:asio_test amuralid$ g++ -g -std=c++14 -I ~/asio-master/asio/include/ -o client_read_so client_read_so.cc -pthread

MacBook-Pro:asio_test amuralid$ ./client_read_so
    Received: Cool!