我试图从阻塞套接字读取,但我想知道read()
返回-1,我认为这意味着当前没有数据可读 - 我希望它会阻塞,直到它可以读取字节数。
我还尝试确保套接字处于阻塞模式,并使用以下命令设置高超时:
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,但我无法找到问题的答案。
更新
如果没有设置超时,read()
也会立即返回(主观)-1
更新2
errno
是107(ENOTCONN, Transport endpoint is not connected)
。
但是客户端同时没有关闭连接(在sleep()
之后write()
确定<{1}}
答案 0 :(得分:4)
你期待什么?你说你有一个非阻塞套接字,所以它当然不会阻塞。如果数据可供读取,则read
上的非阻塞套接字的行为是立即返回一些数据(可能短于请求的数量),并返回-1,errno
设置为{如果没有可用数据,则{1}}或EAGAIN
。
如果您不想要非阻塞行为,为什么要将套接字设置为非阻塞?
编辑:格尔,你已经改变了你的问题。 EWOULDBLOCK
的原因是您尝试从未连接的套接字读取。除非ENOTCONN
或accept
获得套接字,否则必须在其上调用socketpair
才能将其连接到远程地址,然后connect
才会生效。
答案 1 :(得分:3)
这意味着要么超时,要么可能是信号中断了读取。您可以在errno
中使用errno.h
的结果来查看错误是什么,如果您希望错误出现在人类可读的格式中,您可以使用strerror()
或{{1来自perror()
或string.h
更新:根据POSIX规范,您应该在发生超时之前将stdlib.h
(在struct timeval
中定义)设置传递到所需的秒数和微秒数在指定sys/time.h
标志时向setsockopt
发送,而不是将SO_RCVTIMEO
投射到int
。因此,即使您的客户端现在可能出现错误行为并导致不同的错误,如果您向函数发送错误的参数类型,您仍然可能会遇到问题。
答案 2 :(得分:2)
原因在于errno。可能的情景:
[ECONNRESET]
d参数指的是套接字和远程
套接字端被强行关闭。[EAGAIN]
文件标记为非阻塞I / O,没有数据
准备好了。基本上,您使用以下方法进行非阻塞阻止:
do
{
read(...);
} while(errno == EAGAIN);
答案 3 :(得分:1)
超时时返回-1。
不要设置超时,它会永远阻塞(好吧,至少在套接字仍然连接时,无论如何)。
答案 4 :(得分:0)
我已经解决了这个问题 感谢您的所有意见,他们给了我们很大的帮助。
问题在于使用错误的文件描述符。
我将服务器套接字的文件描述符传递给read()
,而不是accept()
返回的客户端套接字的文件描述符。
答案 5 :(得分:0)
read()
可能会阻止,因此如果没有可用数据,则会返回-1
并将errno
设置为EAGAIN
或EWOULDBLOCK
。
如果您想使用read()
,可以使用select()
或poll()
等待套接字上的数据可用性。