Я знаю, что ошибка сломанной трубы возникает, когда сокет на стороне узла закрывается.
Но в своем тесте я заметил, что немедленный вызов send на этой стороне, когда одноранговая сторона закрыта, не всегда приводит к ошибке разрыва канала.
Например:
После закрытия сокета на стороне однорангового узла (я попытался выполнить чистое закрытие, вызвав close, а также ненормальное закрытие, убив однорангового узла), если я попытаюсь отправить 40 байт, я не получу сломанный канал, но, если я попытаюсь отправьте 40000 байт, тогда он сразу же выдает ошибку сломанной трубы.
Что именно вызывает поломку трубы и можно ли предсказать ее поведение?
источник
Текущее состояние сокета определяется активностью проверки активности. В вашем случае это возможно, когда вы выполняете
send
вызов,keep-alive
действие сообщает, что сокет активен, и поэтомуsend
вызов запишет необходимые данные (40 байтов) в буфер и вернется без каких-либо ошибок.Когда вы отправляете больший кусок, вызов send переходит в состояние блокировки.
Страница руководства по отправке также подтверждает это:
Таким образом, при блокировке свободного доступного буфера, если вызывающий абонент уведомлен (с помощью механизма поддержания активности), что другой конец больше не присутствует, вызов отправки завершится ошибкой.
С помощью упомянутой информации трудно предсказать точный сценарий, но я считаю, что это должно быть причиной вашей проблемы.
источник
Может быть, 40 байтов помещаются в буфер канала, а 40000 байтов нет?
Редактировать:
Процесс отправки отправляет сигнал SIGPIPE при попытке записи в закрытый канал. Я не знаю точно, когда отправляется сигнал и какое влияние на это оказывает буфер канала. Вы можете восстановить его, перехватив сигнал с помощью вызова sigaction.
источник
Когда одноранговый узел закрывается, вы просто не знаете, просто ли он прекращает отправку или одновременно отправку и прием. Поскольку TCP позволяет это, кстати, вы должны знать разницу между закрытием и выключением. Если одноранговый узел перестает отправлять и получать, сначала вы отправляете несколько байтов, это будет успешно. Но одноранговое ядро отправит вам RST. Таким образом, впоследствии вы отправляете несколько байтов, ваше ядро отправит вам сигнал SIGPIPE, если вы поймаете или проигнорируете этот сигнал, когда ваша отправка вернется, вы просто получите ошибку Broken pipe, или если вы этого не сделаете, поведение вашей программы по умолчанию дает сбой .
источник
У нас возникла ошибка Broken Pipe после установки новой сети. Убедившись, что порт 9100 открыт и может подключаться к принтеру через порт telnet 9100, мы изменили драйвер принтера с «HP» на «Generic PDF», ошибка сломанной трубы исчезла, и мы смогли успешно выполнить печать.
(RHEL 7, принтеры были торговой маркой Ricoh, конфигурация HP существовала ранее и работала в предыдущей сети)
источник