У меня есть два процесса в системе Centos 6 (Linux 2.6.32), которые разговаривают друг с другом через сокет AF_INET/SOCK_STREAM. Когда я стресс тестирую ссылку, разбивая достаточно небольшие пакеты, чтобы заполнить сокет, а затем выйти из процесса отправки, процесс получения теряет последние 3/4 или около того пакетов.Centos 6 пишите в розетку без проблем?
Как только процесс отправки выходит, опрос приемника() начинает возвращать извержения POLLIN | ПОЛРДХУП | POLLERR | POLLHUP. В какой-то момент он не может прочитать полный пакет, который он ожидает (read() возвращает меньшее число, чем длина переданного), а следующее read() возвращает -1 с errno, установленным в ECONNRESET). Мне, конечно, кажется, что он прочитал все данные в трубе, и больше нечего ждать.
Если я не выйду из процесса отправки после заполнения трубы (просто войдите в бесконечный цикл, пока я не убью его вручную), тогда получатель получит все данные.
Я предполагаю, что это означает, что запись write() s отправителя заканчивается тем, что где-то буферизуется, причем этот буфер получает бросок, если он выходит, вместо того, чтобы возвращать сбой. Отключение Nagle (включение TCP_NODELAY) не изменяет этого поведения.
Код, который делает запись является:
iov[0].iov_base = &len;
iov[0].iov_len = sizeof(uint32_t);
iov[1].iov_base = buf;
iov[1].iov_len = len;
if ((wlen = writev(fd, iov, NELEM(iov))) != (iov[0].iov_len + iov[1].iov_len)) {
... // error handling
(он посылает длину 32-битного следуют данные).
Может ли кто-нибудь дать мне подсказку о том, что происходит, и как я могу достоверно узнать, преуспели ли мои записи()?
Если вы замените вызов writev() двумя раздельными вызовами write(), проблема исчезнет? (или, если нет, характер проблемы становится более очевидным, если у вас есть доступ к отдельным возвращаемым значениям из каждого из двух вызовов write()?) –
Нет, проблема остается. (Кстати, writev() необходимо, потому что без него будет передан первый 4-байтовый пакет, а затем второй пакет будет удерживаться до тех пор, пока не будет принят ACK (если не установлен NODELAY)). – Jabberwock
@Jabberwock * Кстати, writev() необходимо, потому что без него будет передан первый 4-байтовый пакет, а затем второй пакет будет удерживаться до тех пор, пока не будет принят ACK (если не установлен NODELAY) * Если ' writev() 'является« необходимым », приемник неправильно обрабатывает полученные данные как поток, подлежащий разбивке на ** любую ** точку и, таким образом, подвергается всем видам ошибок. –