Сокет TCP отправляет меньшее количество байтов

Я пытаюсь отправить большое количество байтов, используя библиотеку boost.asio, следующим образом:

void tcp_send(boost::asio::io_service &io, const char *dst_ip, uint16 dst_port)
{
    uint8 *sbuff;
    size_t slen;
    ip::tcp::socket sock(io);

    sock.connect(ip::tcp::endpoint(ip::address::from_string(dst_ip), dst_port));

    sbuff = new uint8[100412];
    sbuff[0] = 67;
    sbuff[1] = 193;
    sbuff[2] = 136;
    sbuff[3] = 60;

    boost::asio::async_write(sock, boost::asio::buffer(sbuff, 100412),
             boost::bind((&send_handler), placeholders::error));
}

Когда я проверяю количество переданных байтов с помощью wireshark, отправитель отправляет всегда и только 65536 байтов данных, исключая байты заголовка TCP. Так в чем может быть проблема? Есть ли какой-либо параметр, который мне нужно изменить.

Я запускаю приложение на Linux Ubuntu. Похоже, что максимальное количество передаваемых байтов равно 2^16.

Wireshark TCP Stream Flow


person IoT    schedule 21.05.2014    source источник


Ответы (2)


TCP — это поток. Сколько байтов появляется в дейтаграммах IP или фреймах Ethernet, вас не должно волновать.

Успешный вызов send не обязательно даже означает, что данные уже были отправлены; просто стек TCP принял данные и обещает их отправить (если вы не укажете PSH).

person Jonathon Reinhart    schedule 21.05.2014
comment
Итак, что я должен сделать в моем случае, чтобы все 100412 байт вышли? На самом деле у меня не было проблем, когда я использовал сокеты Беркли напрямую, но теперь у меня есть проблема с обертками boost. - person IoT; 22.05.2014
comment
Не уверен, как вы реализовали остальные свои вещи, но вы можете попробовать отследить их в send_handler. - person Captain Obvlious; 22.05.2014
comment
Пожалуйста, не могли бы вы проверить мое новое редактирование, я предоставил вывод wireshark. send_handler предназначен только для обработки ошибок - person IoT; 22.05.2014
comment
send_handler вызывается, когда отправка завершена, независимо от того, успешна она или нет. Пусть он сообщит вам, был ли отправлен полный буфер или отправка не удалась. Скорее всего, он выходит из строя после отправки 65536 байт. TCP не может отправить 100412 байт в одном пакете, поэтому async_write() должен отправлять несколько пакетов до тех пор, пока buffer не будет исчерпан или не произойдет ошибка. - person Remy Lebeau; 22.05.2014
comment
Я попытался заменить boost::asio::async_write() на boost::asio::write, и операция прошла успешно. Я смог увидеть все байты в wirehark. Может ли кто-нибудь объяснить мне, что происходит? @Remy Вы правы, но я вообще не получаю никаких ошибок в send_handler. - person IoT; 22.05.2014

Я узнал источник проблемы. Прежде всего, я пытался отправить сообщение с помощью функции tcp_Send, и после того, как оно возвращается из вызова, у меня есть программа. Из-за этого стеку TCP не хватает времени, чтобы отправить все пакеты в своем буфере. Так что я должен дать ему некоторое время.

Теперь во втором испытании я оставил приложение запущенным после отправки сообщения, но теперь я получил ошибку в send_handler, в которой указано bad file descriptor. И это из-за того, что объявляемый сокет уничтожается после выхода из функции tcp_send. Поэтому, чтобы решить эту проблему, я должен определить сокет как указатель. Или лучше всего использовать запись вместо async_Write

person IoT    schedule 22.05.2014
comment
Это не приведет к потере данных. Когда вы уничтожаете ip::tcp::socket, базовый сокет закрывается, но все ожидающие данные остаются в буфере отправки сокета для возможной передачи, после чего следует упорядоченное закрытие (TCP FIN). Однако это может быть не все отправлено в момент выхода из вашей программы. - person user207421; 22.05.2014
comment
Я не тестировал это в последнее время, но раньше в Windows (XP и более ранних версиях) выход из процесса отбрасывал все неотправленные данные из сетевого стека, тогда как в системах * nix данные в конечном итоге все равно отправлялись. Настоящая PITA для Windows-программистов, поскольку не было хорошего способа узнать, действительно ли данные были отправлены. - person Dale Wilson; 22.05.2014