2014-05-26 3 views
1

Когда я вызываю async_write(), удаленный одноранговый узел не принимает данные, пока я не позвоню async_write(). Например, у меня есть 3 пакеты, a, b и c:C++ boost :: asio :: async_write отправить проблемы

SendPacket(a); // the remote side receives nothing 
SendPacket(b); // the remote side receives packet a 
SendPacket(c); // the remote side receives packet b 

Это мой код для отправки:

void Session::SendPacket(packet p) 
{ 
    dword len = p.Lenght(); 
    byte* buffer_send = new byte[len + 4]; //4 cause of the header 

    memcpy(buffer_send + 4, p.GetRaw(), len); // copy everything to the buffer +4, 0-4 is header 

    m_codec.EncodePacket(buffer_send, len); 

    boost::asio::async_write(m_socket, boost::asio::buffer(buffer_send, len + 4), 
       boost::bind(&Session::OnPacketSend, this, len + 4, boost::asio::placeholders::error, 
       boost::asio::placeholders::bytes_transferred, buffer_send)); 

} 

void Session::OnPacketSend(int len, const boost::system::error_code &e, size_t bytes_transferred, byte* buf) 
{ 
    // this asynchronously fires when packet data is sent 
    delete[] buf; 
    if (e || bytes_transferred != len) 
    { 
     Stop(); 
     return; 
    } 
} 

И я использую это так:

packet pp; 

pp.WriteWord(0); 
pp.WriteDword(4); 
pp.WriteWord(0); 

SendPacket(pp); 

Кроме того, когда SendPacket() принимает packet по значению вместо ссылки, происходит сбой.

Гр

+0

У вас есть еще одна нить, обслуживающая сервис io? В противном случае составные функции должны будут ждать. Как защитить сокет от конфликтов доступа? Я не вижу, чтобы ты использовал нитку. (Похоже, вы ожидаете, что операция будет завершена «каким-то образом» без фактического завершения кода.) –

+0

Каждый сокет использует 1 io_service, который я получаю из пула, например: http://pastebin.com/F4TSSEBA. Поэтому каждый сеанс находится внутри 1 потока. – NLScotty

+0

Тогда сокет не может сделать какой-либо прогресс вперед, пока нить ничего не делает. Кроме того, вы не можете вызывать 'async_write' до тех пор, пока не завершится предыдущий' async_write' - в противном случае две операции могут чередоваться. –

ответ

2

При небольших объемах данных, записываются в сокет, например, в исходном коде (12 байт ~), один, как правило, наблюдает за поведением данных не посылается, пока последующие данные записываются в гнездо из-за Nagle's algorithm. Короче говоря, многие системы будут пытаться смягчить перегрузку IP/TCP путем объединения небольших исходящих сообщений в одно сообщение, которое затем отправляется. Чтобы явно отключить это поведение на основе каждого сокета, установить параметр boost::asio::ip::tcp::no_delay:

boost::asio::ip::tcp::socket socket(io_service); 
// ... 
boost::asio::ip::tcp::no_delay option(true); 
socket.set_option(option); 

с достаточной пропускной способностью, отключение Нэйгл может привести к более высокой пропускной способности. Тем не менее, по-прежнему стоит рассмотреть протокол приложения и логику гораздо больше, чтобы определить, когда или какие данные могут быть буферизованы, и когда это нужно немедленно отправить.

Смежные вопросы