Поведение recv на неблокирующем сокете TCP до завершения соединения

Друзья,

У меня есть неблокирующий сокет TCP (в AIX). Когда я попытался подключиться(), я получил EINPROGRESS. Мой вопрос: если я вызову recv() до завершения соединения, каким будет (наиболее подходящий) код ошибки?

Я видел, что в случае сбоя соединения и вызова recv() я получаю ECONNREFUSED; означает, что я получил ошибку, соответствующую моей предыдущей попытке подключения(). Следуя той же логике, я должен получить EINPROGRESS для recv(). Я прав в своем подходе?

Если да, возникает другой вопрос: почему такие коды ошибок не включены в число кодов ошибок recv()?


person ultimate cause    schedule 27.10.2010    source источник


Ответы (2)


Я видел, что EAGAIN возвращается только в этом случае, точно так же, как и в случае, когда нет данных для чтения. Для записи в неподключенный сокет вы обычно получаете ENOTCONN, хотя я полагаю, что некоторые платформы могут предоставить вам EAGAIN.

Вот тривиальный скрипт Python для демонстрации:

import socket
# Any address that does not succeed or fail right away will do
ADDR = "192.168.100.100"
PORT = 23
s = socket.socket()
s.setblocking(False)
try:
    s.connect((ADDR, PORT))
except socket.error, e:
    print "Connect gave us",e
try:
    s.recv(1)
except socket.error, e:
    print "Read gave us",e
try:
    s.send("x")
except socket.error, e:
    print "Write gave us",e

Для меня это дает: Connect дал нам (36, 'Операция сейчас выполняется') Read дал нам (35, 'Ресурс временно недоступен') Write дал нам (57, 'Сокет не подключен')

Это EINPROGRESS, EAGAIN и ENOTCONN соответственно.

person nickm    schedule 31.10.2010
comment
Спасибо, это разумно. Я подожду еще несколько ответов, прежде чем принять это. - person ultimate cause; 31.10.2010

Вы работаете с неблокирующим сокетом, который отлично подходит для возврата EINPROGRESS, который указывает на то, что установление соединения еще не завершено, это задокументировано на странице подключения:

   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).

Поэтому вам понадобится select/pool, чтобы убедиться, что сокет доступен для записи, и получить ошибку от SO_ERROR.

person fluter    schedule 18.05.2015