Что означает ECONNABORTED при попытке подключения сокета?

Я использую python 2.7 на машине ubuntu.

клиент пытается подключиться к серверу. Я получаю EINPROGRESS, который ожидается для неблокирующих сокетов.

чтобы проверить, удалось ли соединение, я делаю то, что предлагает man-страница для {connect}:

# EINPROGRESS The socket is nonblocking and the connection cannot be
# completed immediately.  It is possible to select(2) or poll(2) for
# completion by selecting the socket for writing.  After select(2)
# indicates writability, use getsockopt(2) to read the SO_ERROR option at
# level SOL_SOCKET to determine whether connect() completed successfully
# (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error
# codes listed here, explaining the reason for the failure)

когда сервер отключен, это дает мне ECONNREFUSED. Пока все хорошо.

когда соединение не удается, я хочу попробовать еще несколько раз.

: во второй раз, когда я пытаюсь подключить тот же сокет, {connect} отправляет мне ECONNABORTED. Этого нет на главной странице {connect}. Что это значит?

2 ответов


ECONNABORTED устанавливается в двух местах исходного кода сокета ядра Linux.

на errno man page и / include/asm-generic / errno.h

#define ECONNABORTED 103 /* Software caused connection abort */

на первый находится в функции, которая определяет syscall accept4 на / net / socket.c.

Соответствующий Исходный Код

1533         if (upeer_sockaddr) {
1534                 if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
1535                                           &len, 2) < 0) {
1536                         err = -ECONNABORTED;
1537                         goto out_fd;
1538                 }
1539                 err = move_addr_to_user((struct sockaddr *)&address,
1540                                         len, upeer_sockaddr, upeer_addrlen);
1541                 if (err < 0)
1542                         goto out_fd;
1543         }

соответствующее объяснение логики приведено ниже.

если определен адрес однорангового сокета из пространства пользователей и если новый сокет не имеет имени, установите состояние ошибки в ECONNABORTED и goto метка out_fd.

на второй находится в функции, которая определяет символ inet_stream_connect на /нетто/IPv4 и равен af_inet.c.

Соответствующий Исходный Код

645         /* Connection was closed by RST, timeout, ICMP error
646          * or another process disconnected us.
647          */
648         if (sk->sk_state == TCP_CLOSE)
649                 goto sock_error; 

662 sock_error:
663         err = sock_error(sk) ? : -ECONNABORTED;
664         sock->state = SS_UNCONNECTED;
665         if (sk->sk_prot->disconnect(sk, flags))
666                 sock->state = SS_DISCONNECTING;
667         goto out;

соответствующее объяснение логики приведено ниже.

единственный код, который имеет Гото к sock_error метка в inet_stream_connect - это проверка, чтобы увидеть, был ли сокет закрыт первым, таймаутом, другим процессом или ошибкой.

на sock_error ярлык Если мы можем восстановить отчет об ошибке сокета, сделайте это, иначе состояние ошибки ECONNABORTED

как Селадекомментарий я также рекомендую открывать новый сокет каждый раз.


см. страницу руководства для errno. На FreeBSD вы можете найти его как intro(2). Он говорит:

53 программное обеспечение ECONNABORTED вызвало прерывание соединения. Прерывание соединения было вызвано внутренним для вашей хост-машины.

что касается того, почему это происходит, вам придется искать сокеты в источнике ядра Linux. Только на FreeBSD accept Кажется, возврат ECONNABORTED.