当我打开O_NONBLOCK时,我得到;0“;及;I/O错误“;
当我打开当我打开O_NONBLOCK时,我得到;0“;及;I/O错误“;,c,linux,tcp,redhat,C,Linux,Tcp,Redhat,当我打开O_NONBLOCK时,我的连接len返回0,我的errno返回EIO。我希望len是-1,errno是EAGAIN。根据我得到的信息,我可以假设初始连接存在问题。我不明白的是为什么我会得到它。如果我在打开O_NONBLOCK的地方注释掉,我根本就没有这个问题。我是否错过了一些关于打开O_NONBLCOK的内容 我的代码(MAIN()) 编辑 也许我第一次没有说清楚,我知道errno和len与s_recv 我的问题是,当我打开O_NONBLOCK时,我得到了不想要的结果s_recv的错误
O_NONBLOCK
时,我的连接len返回0
,我的errno返回EIO
。我希望len是-1
,errno是EAGAIN
。根据我得到的信息,我可以假设初始连接存在问题。我不明白的是为什么我会得到它。如果我在打开O_NONBLOCK
的地方注释掉,我根本就没有这个问题。我是否错过了一些关于打开O_NONBLCOK
的内容
我的代码(MAIN())
编辑
也许我第一次没有说清楚,我知道errno和len与s_recv
我的问题是,当我打开O_NONBLOCK时,我得到了不想要的结果s_recv
的错误号是EIO及其
莱恩是0。如果我关闭关闭O_NONBLOCK
,那么我所有的问题都会消失;len为1或更多,而errno不为
需要检查
以下是我预期的情景示例:
在第一个坏的场景中,s_recv
的Len为0或-1,errno不是EAGAIN,连接被重置
在第二场比赛中,赛昂里奥的伦比是-1,厄尔诺是伊根。这是在什么时候的示例场景
O_NONBLOCK根据手册页打开
在良好的sceanrio
s_recv
中,len大于1,无需检查errno 在下次读取之前,对O_NONBLOCK
的更改不相关
因此,在调用fcntl
之前,必须先检查len
和errno
。当然,您必须检查fcntl
的返回值,因为它也可能失败
总之,len==0
和errno==EIO
与更改为O\u NONBLOCK
无关,而是与之前的s\u recv
有关
此外,请注意您的
if (len == -1 || len == 0 && errno != EAGAIN)
与
if (len == -1 || (len == 0 && errno != EAGAIN) )
这没有意义,因为如果返回值不是-1
,则必须忽略errno。如果返回值为0
,则对等方已关闭连接
更新:
我构建了一个简单的echo客户端
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
error("socket");
he = gethostbyname("localhost");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ((struct in_addr*)he->h_addr)->s_addr;
addr.sin_port = htons(7); /* echo */
if (connect(fd, (struct sockaddr*) &addr, sizeof(addr)) == -1)
error("connect");
while (fgets(buf, sizeof(buf), stdin)) {
n = strlen(buf);
printf("fgets=%d, %s", n, buf);
if (send(fd, buf, n, 0) == -1)
error("send");
n = recv(fd, buf, sizeof(buf), 0);
if (n == -1)
error("recv");
printf("recv=%d, %s", n, buf);
flags = fcntl(fd, F_GETFL, 0);
printf("flags=%d\n", flags);
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
error("fcntl");
}
设置O_NONBLOCK
后,我收到
errno=11recv:资源暂时不可用 如果我在循环之前移动
fcntl(O_NONBLOCK)
,一切正常
因此,在读取或写入套接字后不建议使用非阻塞。问题在于线路:
if (len == -1 || len == 0 && errno != EAGAIN)
这相当于
if (len == -1 || (len == 0 && errno != EAGAIN))
因此,如果没有可用的数据(len==-1
),您将不会选中errno
,只会无条件地标记错误并退出。此外,当存在EOF(len==0
)时,不会设置errno,因此检查它将给出以前调用中发生的任何情况
您可能想要:
if ((len < 0 && errnor != EGAIN) || len == 0) {
ReceiveError = (len < 0) ? errno : 0;
if((len<0&&errnor!=EGAIN)| len==0){
ReceiveError=(len<0)?错误号:0;
此外,如果fcntl出现错误,则会出现错误errno(尽管我预计不会发生这种情况——使用GETFL/SETFL可能看到的唯一失败是EBADF)您可能想在recv调用之前进行fcntl调用。为什么在读取后设置
O_NONBLOCK
?如果是非阻塞套接字,最好使用选择/poll
。为什么在循环中和在s_recv之后进行fcntl调用?为什么您认为fcntl不能在s_recv之后更改错误号?Eddy_EM:我最初设置了O_Non为调试目的阅读后阻塞。我计划将所有内容移动到正在进行初始连接的函数。oleg_g:这是一个快速实现,用于执行一些快速调试。我理解您的观点,它应该设置在while
循环之外。我确信我理解您的第二个问题…我不想改变错误o、 只是检查一下。“当我打开o_NONBLOCK时,我的连接len返回0,errno返回EIO。”1.当recv()时返回零,对等方已关闭连接。2.errno的值不相关,除非返回了-1。请阅读“手册”页。这不是一个真正的问题。也许我第一次没有正确解释这一点,我理解len和errno与s_recv
有关。我的问题是,当我打开O_NONBLOCK
Mys_rec时v
给了我不想要的结果;len是0,errno是EIO。如果我注释掉代码,打开O_NONBLOCK
一切正常。例如:在第一个好场景中,我的s_recv
len是1或更多,不需要检查errno。在第二个好场景中,我的s_recv
len是-1(基于O_非块)在糟糕的情况下,如果连接中断或发生其他情况,lenis@WorkerBee如果len==0
,您必须忽略errno
,因为errno
仅在len==1
时设置。如果您得到len==0
,则表示EOF。我相应地更新了我的答案。Olaf dietsche-Ok,应该s\u recv
如果启用了O_NONBLOCK
,则返回0?我询问的原因是如果我对打开O_NONBLOCK
的位置进行注释,则我不会遇到任何问题。@WorkerBee这应该是无关的,但我没有在读取后设置O_NONBLOCK
的经验。
if ((len < 0 && errnor != EGAIN) || len == 0) {
ReceiveError = (len < 0) ? errno : 0;