I try to send a large data (1mb+) from a server to a client using the boost's asio library.
I split the data into chunks of size 16000 and use async_write_some to send them. I read the data with async_read or async_read_some in the client.
When both the server and the client are my local machine, everything works fine and I can send 10mb+ data without any problems.
When I use a different machine to send the data it is ok with data less than 1mb. but when the data size is 1mb+ there is a data loss between chunks when the client reads it. I am using an ethernet cable to connect the server and the client (the network is really reliable).
When I put a timeout between sending chunks like:
std::this_thread::sleep_for(30ms)
The client could get the whole data without any loss.
Could somebody give me some hints what is happening and how can I correct mistakes? TCP requires that no data lost must be occurred in any situation.
Edit: Here is the send logic
void SendData(const char* data, int size) {
const int tr_size = std::min(CHUNK_SIZE, size);
socket_->async_write_some(asio::buffer(data, tr_size),
[this, data = data + tr_size, size = size - tr_size]
(const std::error_code &error, size_t bytes_transferred){
if(!error && size > 0) {
SendData(data, size);
} else if(socket_ && socket_->is_open()) {
socket_->close();
}
});
}
Here is the receive logic
void ReceiveData(char* data, size_t size)
{
socket_.async_read_some(asio::buffer(data, size), [this, data, size]
(const std::error_code &error, size_t bytes_transferred) mutable{
if(!error) {
assert(size >= bytes_transferred);
size -= bytes_transferred;
data += bytes_transferred;
}
if(error) {
return;
}
if(size > 0) {
ReceiveData(data, size);
}
});
The commenters already spot the problem: you should be using write_some repeatedly until the full buffer has been sent.
Of course, this task is so common, why not use asio::async_write
which does just that?
void SendData(const char* data, int size) {
const int tr_size = std::min(CHUNK_SIZE, size);
async_write(*socket_, asio::buffer(data, tr_size),
[this, data = data + tr_size, size = size - tr_size]
(std::error_code error, size_t /*bytes_transferred*/){
if (error) {
std::cerr << "async_write: " << error.message() << std::endl;
}
socket_->close();
});
}