2011-05-16 52 views
2

我想从阻塞套接字读取,但我想知道read()返回-1,我认为这意味着目前没有数据要读取 - 我希望它阻塞,直到它可以读取字节量。套接字:为什么使用ENOTCONN阻塞read()会失败?

我也试图确保插座处于阻塞模式,并且已高超时使用SET:

int setBlockingIO(int fd) 
{ 
     int flags = fcntl(fd, F_GETFL); 
     fcntl(fd, F_SETFL, flags & (~O_NONBLOCK)); 
     int nTimeout = 30000; // 30 seconds 
     setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int)); 
} 

但是,这并没有改变任何东西。

我的问题:

  • 我有什么做read()really block?
  • 是否有一些缺陷,我会打? (在我的程序中的错误?)

我知道这个主题有another question,但在那里我找不到我的问题的答案。

UPDATE

没有设置超时,read()也返回(subjectivly)立即-1

UPDATE 2

errno是107(ENOTCONN, Transport endpoint is not connected)。 但客户端侧具有不同时关闭连接(在write()之后由长sleep()确保)

+2

'man read'并读取'errno'来确定发生的错误,但不一定按顺序。 – 2011-05-16 13:44:03

回答

3

这意味着要么有超时,要么可能是信号中断了读取。您可以使用errno的结果errno.h看看是什么错误,如果你想在一个人类可读的格式化的错误,你可以使用从string.hstrerror()perror()stdlib.h

更新:根据在POSIX规范中,您应该在指定SO_RCVTIMEO标志时将struct timeval(定义在sys/time.h中)设置为发生超时之前所需的秒数和微秒数,而不是将int转换为const char*。因此,即使您的客户端可能会错误地行为并导致不同的错误,但如果您将错误的参数类型发送到该函数,仍然可能导致问题进一步恶化。

+0

谢谢。原因是连接已经被客户端关闭(因为意外的客户端行为,请参阅http://stackoverflow.com/questions/6018974/sockets-what-is-causing-read-to-return-einval) – MRalwasser 2011-05-16 14:37:38

+0

修复客户端后,同样的错误又回来了。我已经更新了这个问题。 – MRalwasser 2011-05-16 14:52:27

+0

好的,我已经添加了对我的答案的更新,希望有所帮助。 – Jason 2011-05-16 14:59:24

1

它在超时时返回-1。

不要设置超时,它会永远阻塞(至少在套接字仍然连接的情况下)。

+0

超时设置为30秒,但似乎立即返回(<0.1秒)。但即使没有设置超时,行为也是一样的。 – MRalwasser 2011-05-16 13:51:52

2

原因在于errno。可能的情形:

  • [ECONNRESET]的d参数指的是插座,并且远程 插座端被强制关闭。
  • [EAGAIN]该文件被标记为非阻塞I/O,并且没有数据 准备好被读取。

基本上,你让无阻塞阻止使用:

do 
{ 
    read(...); 
} while(errno == EAGAIN); 
4

你有什么期望?你说你有一个非阻塞的套接字,所以当然不会阻塞。 read上的非阻塞套接字的行为是在数据可用于读取时立即返回一些数据(可能短于所请求的数量),并且在errno设置为EAGAINEWOULDBLOCK(如果没有数据可用)时返回-1。

如果你不想要非阻塞行为,为什么你将套接字设置为非阻塞?

编辑: Grr,你已经改变了你的问题。 ENOTCONN的原因是您试图从未连接的套接字读取数据。除非通过acceptsocketpair获得套接字,否则必须在其上调用connect将其连接到远程地址,然后read才能工作。

0

我已经解决了这个问题。
谢谢你的评论,他们给了我很大的帮助。

问题是错误的文件描述符的用法。

我通过服务器套接字的文件描述符read(),而不是客户端套接字其中accept()返回的文件描述符。

+1

很高兴你知道这个问题:-) – Jason 2011-05-16 15:42:54

+0

然后你可以接受一个答案,告诉你检查'errno',或者其他帮助你解决问题的东西。 – 2011-05-18 02:15:05

0

read()可能阻塞,因此,如果没有可用数据,它将返回-1并设置errnoEAGAINEWOULDBLOCK

如果您要使用read(),您可以使用select()poll()等待套接字上数据的可用性。

+0

这是错误的。在阻塞模式下,read()不会返回EAGAIN(除了(可选)超时达到外)。您正在描述非阻塞性读取。 – MRalwasser 2011-05-16 15:41:30