2016-10-19 3 views
2

Я пишу клиента, который должен прослушивать сокет домена. Я открываю синхронное соединение, выполняю синхронную запись, и я знаю, что сервер отправляет действительный ответ, потому что я использую socat для eavesdrop в сокете.Asio не получает ответа от удаленной системы

За исключением моего asio::read() вызывается, но никогда не возвращает никаких данных. Буфер, который я передаю ему, всегда пуст. Вот мой код:

void operator>>(const vector<unsigned char> input, Socket &socket) { 
     const size_t size = input.size(); 
     const size_t bytes = asio::write(socket.connection_socket, asio::buffer(input, size)); 
     if (bytes != size) { 
     const std::error_code ec; 
     throw std::system_error(ec, fmt::format("Tried to send {0} bytes but sent {1} instead.", size, bytes)); 
     } 
     string buffer; 
     asio::read(socket.connection_socket, asio::buffer(buffer)); 
     std::cerr << buffer << std::endl; 
    } 

Это свойство, которые я использую для подключения к гнезду:

io_service run_loop; 
stream_protocol::socket connection_socket; 
datagram_protocol::endpoint domain_socket_ep; 

Socket является простым классом, который окутывает весь код Asio, где выше объявляется перегрузка оператора ,

ответ

1

Функция asio::read будет читать не болееasio::buffer_size(asio::buffer(buffer)) байт. В вашем случае buffer пуст, поэтому он будет читать не более нуля байт.

Asio никогда не будет изменять размеры буферов, которые вы передадите в него, и поэтому вам необходимо изменить размер buffer на максимальный размер, который вы ожидаете получить.

Кроме того, функция asio::read может фактически читать меньше байтов, а затем размер входного буфера. Фактический размер, который он считывает, возвращается из этой функции. Таким образом, если вы хотите точно прочитать/записать количество байтов, которые могут поместиться в буфер, вам нужно сделать что-то вроде этого:

void read_to_buffer(asio::ip::tcp::socket& s, asio::buffer buffer) { 
    size_t read = 0; 
    size_t n = asio::buffer_size(buffer); 
    while (read < n) { 
     read += asio::read(s, buffer + read)); 
    } 
} 

void write_from_buffer(asio::ip::tcp::socket& s, asio::buffer buffer) { 
    size_t written = 0; 
    size_t n = asio::buffer_size(buffer); 
    while (written < n) { 
     written += asio::write(s, buffer + written)); 
    } 
} 

void operator>>(const vector<unsigned char> input, Socket &socket) { 
     // TODO: convert between host and network byte order 
     auto& s = socket.connection_socket; 
     { 
     const uint32_t size = input.size(); 
     write_from_buffer(s, asio::buffer(&size, sizeof(size)); 
     write_from_buffer(s, asio::buffer(input)); 
     } 
     { 
     uint32_t size = 0; 
     read_to_buffer(s, asio::buffer(&size, sizeof(size))); 
     string payload(size, 'x'); 
     read_to_buffer(s, asio::buffer(payload)); 
     std::cerr << payload << std::endl; 
     } 
} 
+0

Не уверен, что я понимаю. Запись в сокет в порядке, asio просто не читает из него. Зачем вам писать и читать дважды? Кроме того, не read_to_buffer() делает то же самое, что и asio :: read_some? – ruipacheco

+0

«_asio просто не читает из него», передавая строку с нулевым значением в функцию asio :: read, которую вы сообщаете asio, чтобы читать нулевые байты. Сокеты TCP не знают, сколько байтов вы отправили. "_ как и asio :: read_some_", извините, я не вижу функцию 'asio :: read_some', указанную в [API] (http://www.boost.org/doc/libs/1_62_0/doc/html/ boost_asio/reference.html), о котором вы говорите? –

+0

Я имел в виду socket.read_some(): http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_stream_socket/read_some/overload1.html – ruipacheco

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