连接完成之前recv在非阻塞TCP套接字上的行为

时间:2010-10-27 15:23:35

标签: nonblocking recv

我有一个非阻塞的TCP套接字(在AIX上)。当我尝试连接()时,我得到了EINPROGRESS。我的问题是,如果我在连接完成之前调用recv(),那么(最适合的)错误代码是什么?

我看到了,如果连接失败,我调用recv(),我得到了ECONNREFUSED;意味着我收到了与我之前的connect()尝试相对应的错误。采用相同的逻辑,我应该得到recv()的EINPROGRESS。我的做法是对的吗?

如果是,这就提出了另一个问题 - 为什么这些错误代码不包含在recv()的错误代码中?

2 个答案:

答案 0 :(得分:3)

在这种情况下我只看到了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 :(得分:1)

您正在使用非阻塞套接字,这非常适合返回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获取错误。