Будет ли системный вызов write() блокировать дальнейшую работу до тех пор, пока не будет задействовано read(), или наоборот?

Написано как часть клиент-сервера TCP/IP:

Сервер:

write(nfds,data1,sizeof(data1));
usleep(1000);
write(nfds,data2,sizeof(data2));

Клиент:

read(fds,s,sizeof(s));
printf("%s",s);
read(fds,s,sizeof(s));
printf("%s",s);

Без usleep(1000) между двумя вызовами write(), клиент печатает data1 дважды. Почему это?

Фон:

Я делаю программу клиент-сервер, где сервер должен отправлять два последовательных фрагмента информации после их получения через сеть (сокет); nfds дескриптор файла мы получаем accept(), На стороне клиента мы получаем эту информацию через read; Вот fds это дескриптор файла, полученный через socket(),

Моя проблема в том, что когда я НЕ использую usleep(1000) между write() функции, клиент просто печатает информацию, представленную data1 дважды, вместо печати data1 и затем data2. Когда я положил в usleep() все в порядке. ПОЧЕМУ это происходит? Является write() блокирование операции до тех пор, пока буфер не будет прочитан или не будет read() блокировать операцию, пока информация не будет записана в буфер? Или я полностью со страницы?

1 ответ

Вы делаете несколько ложных предположений. В TCP нет ничего, что гарантировало бы, что одна отправка равна одной полученной. На обоих концах много буферизации, и есть преднамеренные задержки при отправке, чтобы объединить пакеты (алгоритм Nagle). Когда вы звоните read(), или же recv() и друзья, вам нужно сохранить результат в переменной и проверить его для каждого из следующих случаев:

  • -1: ошибка: изучить / войти / распечатать errno, или же strerror(), или позвоните по телефону perror()и в большинстве случаев закройте сокет и выйдите из цикла чтения.
  • 0: конец потока; владелец закрыл соединение; закройте сокет и выйдите из цикла чтения.
  • положительное значение, но меньше, чем вы ожидали: продолжайте читать и накапливать данные, пока у вас не будет все, что вам нужно.
  • положительное значение больше ожидаемого: обработайте данные, которые вы ожидали, и сохраните остаток для следующего раза.
  • именно то, что вы ожидали: обработать данные, отбросить все и повторить. Это не простой случай, и он редок, но это единственный случай, для которого вы сейчас программируете.

Не добавляйте сны в сетевой код. Это не решает проблемы, оно только задерживает их.

Другие вопросы по тегам