2016-10-26 8 views
3

Я вызываю async_read в соке домена, и моя проблема в том, что иногда я получаю данные, а иногда и нет, хотя удаленная система всегда возвращает данные. Кажется, я могу читать из сокета, если я делаю пошаговую отладку. Если я автоматизирую модульные тесты, они, похоже, слишком быстро работают для возвращаемых данных, что является нечетным, поскольку целая цель асинхронных методов - ждать ответа.Heisenbug при выполнении афропростой чтения из сокета

У меня есть их как свойства моего класса:

io_service run_loop; 
stream_protocol::socket connection_socket; 
datagram_protocol::endpoint domain_socket_ep; 
vector<unsigned char>read_buffer; 

Я делаю запись:

void operator>>(const vector<unsigned char> input, shared_ptr<Socket>socket) { 
    asio::async_write(socket->connection_socket, asio::buffer(input), std::bind(&Socket::write_handler, socket, std::placeholders::_1, std::placeholders::_2)); 
    socket->run_loop.reset(); 
    socket->run_loop.run(); 
} 

В обратном вызове записи я прочитанный:

void Socket::write_handler(const std::error_code &ec, const size_t size) noexcept { 
    const size_t avail = connection_socket.available(); 
    if (!read_buffer.empty()) { 
    read_buffer.clear(); 
    } 
    asio::async_read(connection_socket, asio::buffer(read_buffer, avail), std::bind(&Socket::read_handler, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); 
} 

Я пытался обертывание функции чтения в while(read_buffer.size() < avail), но это просто бросило меня в бесконечный цикл.

Мне определенно чего-то не хватает, я просто не могу понять, что и тот факт, что это работает при работе поэтапно, просто делает его еще хуже.

+0

Что такое выделенный размер для «входа» и read_buffer? – Arunmu

+0

Вход отправляется пользователем, и в моих тестах он никогда не пуст. read_buffer установлен на количество байтов в сокете. – ruipacheco

ответ

4

На считывающей стороне вещей:

Вы никогда не упоминают тип read_buffer. Там не много мы знаем о том, что .clear() делает, но если он делает то, что следует из названия, он будет недействителен использовать asio::buffer(read_buffer, avail) без предварительного read_buffer.resize(avail)


Почему у вас

void operator>>(const vector<unsigned char> input, shared_ptr<Socket>socket) { 
    asio::async_write(socket->connection_socket, asio::buffer(input), std::bind(&Socket::write_handler, socket, std::placeholders::_1, std::placeholders::_2)); 
    socket->run_loop.reset(); 
    socket->run_loop.run(); 
} 

Вместо например

void operator>>(const std::vector<unsigned char> input, std::shared_ptr<Socket> socket) { 
    boost::system::error_code ec; 
    size_t transferred = boost::asio::write(socket->connection_socket, boost::asio::buffer(input), ec); 
    socket->write_handler(ec, transferred); 
} 

Если вы не хотите асинхронных операций, не используйте их. Это, по крайней мере, намного проще. Следующий пример будет сошедшие (если вы убедитесь, что io живет дольше, чем любой сокет, который использует его):

Live On Coliru

#include <boost/asio.hpp> 

struct Socket { 
    boost::asio::io_service& svc; 
    boost::asio::ip::tcp::socket connection_socket; 

    Socket(boost::asio::io_service& svc) : svc(svc), connection_socket(svc) {} 

    void write_handler(boost::system::error_code ec, size_t bytes_transferred) { 
    } 
}; 

void operator>>(const std::vector<unsigned char> input, std::shared_ptr<Socket> socket) { 
    boost::system::error_code ec; 
    size_t transferred = boost::asio::write(socket->connection_socket, boost::asio::buffer(input), ec); 
    socket->write_handler(ec, transferred); 
} 

int main(){ 
    boost::asio::io_service io; 
    auto s = std::make_shared<Socket>(io); 

    std::vector<unsigned char> v { 100, 'a' }; 
    v >> s; 
} 
+0

Мои записи прекрасны, это ошибки чтения. read_buffer определяется в первом блоке кода и, наконец, мне нужны операции async. Почему я не хочу? – ruipacheco

+1

Потому что вы их не используете. До тех пор, пока у вас есть единственный 'io_service' с сокетом и' run() 'для завершения, он эффективно синхронный. Если вы хотите асинхронно, время жизни вектора «input» полностью неадекватно. – sehe

+0

Теперь, когда я вижу определение 'read_buffer', действительно ясно, что произошла ошибка. Размер буфера равен 0, поэтому все чтения получают буфер нулевой емкости. – sehe