2
votes

I am trying to learn boost::asio and I have some problems with boost::asio::write(), socket->write_some(). From what I read until now I learn that boost::asio::write assure that all data was transfer while socket->write doesn't do that because is using send from OS and this doesn't guarantee full transmission.

Here is a part of my client/server app.

server

void server::session(socket_ptr sock)
{
char data[MAX_SIZE] = {};
bool flag = false;
sprintf(data,"On the server are %d users.",user_vector.size());

//boost::asio::write(*sock, boost::asio::buffer(data, strlen(data)));
sock->write_some(boost::asio::buffer(data, strlen(data)));

cleanMemory(data,strlen(data));
try
{
    for (;;)
    {
        boost::system::error_code error;
        size_t length = sock->read_some(boost::asio::buffer(data), error);
        //boost::asio::write(*sock, boost::asio::buffer(data,strlen(data)));
        cout << std::endl << data;
        cleanMemory(data, strlen(data));
        if (error == boost::asio::error::eof)
        {
            std::vector<user_detail>::iterator it = user_vector.begin();
            for (; it!= user_vector.end();)
            {
                std::pair<socket_ptr, int> user = *it;
                if (user.first == sock)
                {
                    cout << "User " << user.second << " leave server." << std::endl;
                    cout << std::endl << "Connection has been closed." << std::endl;
                    it = user_vector.erase(it);
                    flag = true;
                    break;
                }
                else
                    ++it;
            }
            if (flag)
                break;
        }
    }
}
catch (const std::exception&e) {
    std::cerr << "Error in threead : " << e.what() << endl;
}
}

client

size_t length = s.read_some(boost::asio::buffer(buf,100)); //OK DATA RECEVIED
    //boost::asio::read(s, boost::asio::buffer(buf, 100));//FAIL TO RECEIVE DATA
    cout.write(buf,strlen(buf));

The problem is on the client side. If I use:

size_t length = s.read_some(boost::asio::buffer(buf,100));

Works ok and data is recevide but if i use:

boost::asio::read(s, boost::asio::buffer(buf, 100));

Data is lost.

Question:

  1. If the server sends data, for example using boost::asio::write client need to use boost::asio::read or can also use socket.read_some()?
  2. What is more exactly connection between boost::Asio::read and socket->read_some, and why does this work only if i use s.read_some(boost::asio::buffer(buf,100));?
1

1 Answers

2
votes

boost::asio::read() will read until

a) all 100 bytes has been read, or

b) there is an error, or

c) there is an end-of-stream condition.

It is a compound operation. One of the effects of that is that it can both return an error and have read some data.

For example, if 50 bytes are read and then the stream enters an eof condition, the bytes_transferred will be 50 and the error_code returned will indicate end of file.

With a compound operation it's important to check the bytes_transferred before you check the error.