Подтвердить что ты не робот

Что означает ECONNRESET в контексте сокета AF_LOCAL?

Я понимаю, что для сокетов TCP ECONNRESET имеет какое-то отношение к пакетам RST. Но я также видел ошибки ECONNRESET для сокетов AF_LOCAL, при вызовах read() и write(). Что это значит? Как ECONNRESET отличается от read(), возвращающего 0 или write(), бросающего EPIPE?

4b9b3361

Ответ 1

Похоже, что ECONNRESET означает, что другая сторона закрыла соединение, не читая выданные данные, которые были отправлены ему, и может быть запущена как для чтения(), так и для записи(). Но точное поведение зависит от операционной системы.

EPIPE

Кажется, срабатывает, когда одна запись() s в уже созревший сокет, и нет выдающихся исходящих данных. Применяется как для сокетов PF_LOCAL, так и для TCP. Пример (Ruby):

a, b = UNIXSocket.pair
b.close
a.write("foo")   # => EPIPE, on all OSes

read() возвращает 0

Запускается, когда другая сторона закрыла соединение, и нет выдающихся исходящих данных. Применимо к сокетам PF_LOCAL и TCP.

a, b = UNIXSocket.pair
b.close
a.read    # => 0 bytes, on all OSes

ECONNRESET

В Linux он ведет себя следующим образом:

Запускается, когда имеются выдающиеся исходящие данные, которые еще не были записаны на другую сторону. read() запускает его как для сокетов PF_LOCAL, так и для TCP, но write() запускает его только для сокетов TCP; Соединители PF_LOCAL запускают EPIPE.

См. примеры для конкретного поведения ОС. Пожалуйста, внесите свой вклад, если вы знаете, как ведут себя другие ОС.

Пример 1: чтение() в сокете PF_LOCAL

a, b = UNIXSocket.pair
a.write("hello")
b.close
a.read
# Linux: ECONNRESET
# OS X : returns 0 bytes

Пример 2: read() в сокете TCP

# Side A                                # Side B
                                        s = TCPServer.new('127.0.0.1', 3001)
                                        c = s.accept
c = TCPSocket.new('127.0.0.1', 3001)
c.write("hello")
                                        c.close
c.read
# Linux: ECONNRESET
# OS X : returns 0 bytes

Пример 3: write() в сокете PF_LOCAL

a, b = UNIXSocket.pair
a.write("hello")
b.close
a.write("world")
# Linux: EPIPE and not ECONNRESET
# OS X : EPIPE and not ECONNRESET

Пример 4: write() в сокете TCP

# Side A                                # Side B
                                        s = TCPServer.new('127.0.0.1', 3001)
                                        c = s.accept
c = TCPSocket.new('127.0.0.1', 3001)
c.write("hello")
                                        c.close
c.write("world")
# Linux: ECONNRESET
# OS X : no error