Поведение recv на неблокирующем TCP-сокете до завершения соединения - PullRequest
1 голос
/ 27 октября 2010

Друзья

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

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

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

Ответы [ 2 ]

3 голосов
/ 31 октября 2010

Я видел только возвращение 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, «Операция сейчас выполняется»). Чтение дал нам (35, «Ресурс временно недоступен»). Запись дал нам (57, «Сокет не подключен»)

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

1 голос
/ 18 мая 2015

Вы работаете с неблокирующим сокетом, который идеально подходит для возврата 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).

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

...