gpt4 book ai didi

c - 当我打开 O_NONBLOCK 时,我得到 "0"和 "I/O error"

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:53 25 4
gpt4 key购买 nike

当我打开 O_NONBLOCK 时,我的连接 len 返回 0 并且我的 errno 返回 EIO。我希望 len 为 -1 并且 errno 为 EAGAIN。根据我得到的信息,我可以假设初始连接存在问题。我不明白的是为什么我得到它。如果我在打开 O_NONBLOCK 的地方注释掉我根本就没有这个问题。关于打开 O_NONBLCOK 我是否遗漏了什么?

我的代码(MAIN())

long len;

//Var for O_NONBLOCKING
int flags;

printf("R thread - starting\n");

MainTcpipIndex = TcpipIndex = 0;
while ( fMainShutdown == FALSE )
{

s_MuxWait(5000, "", &hevTcpipBuffAvail[MainTcpipIndex], 0);
if ( hevTcpipBuffAvail[MainTcpipIndex] == 0)
continue;

len = s_recv( lSocket, TcpipRecord[MainTcpipIndex].TcpipBuffer,
sizeof(TcpipRecord[MainTcpipIndex].TcpipBuffer));

//initialize flags var
flags = fcntl(lSocket, F_GETFL, 0);

//turns on O_NONBLOCKING
fcntl(lSocket, F_SETFL, flags | O_NONBLOCK);

if (len == -1 || len == 0 && errno != EAGAIN) //0 = connection broken by host
{
ReceiveError = errno;
hevReceiveError = 1;
printf("R_main - set hevReceiveError ON\n");
pthread_exit(NULL);
}
//catches O_NONBLOCK
if (len == -1 && errno == EAGAIN)
{
LogMessage(&LogStruct, INFO, LOGQUEUE + LOGSCREEN, "Caught the
O_NONBLOCKING\n");
len = 0;
continue;
}

// Record Length
TcpipRecord[MainTcpipIndex].ulTcpipBufLen = len;

// Tell T Thread we have a message
hevTcpipBuffUsed[MainTcpipIndex] = 1;
hevTcpipBuffAvail[MainTcpipIndex] = 0;

// Maintain Index
if ( ++MainTcpipIndex >= MAX_TCPIP_BUFFS )
MainTcpipIndex = 0;

}//end while

编辑

可能我第一次没有说清楚,我理解errno和len与s_recv有关我的问题是当我打开 O_NONBLOCK 时我得到了不想要的结果; s_recv 的 errno 是 EIO 及其len 为 0。如果我关闭 O_NONBLOCK,那么我所有的问题都会消失; len 是 1 或更多,errno 不是需要检查。

以下是我预期的场景示例:

第一个坏场景s_recv的Len为0或-1,errno不为EAGAIN,连接被重置。

在第二个坏场景中,s_recv 的 Len 是 -1,errno 是 EAGAIN。这是预期的情况O_NONBLOCK 是根据手册页打开的。

在好的sceanrio中s_recv的len大于1,不需要检查errno。

最佳答案

O_NONBLOCK 的更改在next 读取之前不相关。

因此,在调用 fcntl 之前,您必须检查 lenerrno 。当然,您必须检查 fcntl 的返回值,因为它也可能会失败。

总而言之,len == 0errno == EIOO_NONBLOCK 的更改无关,但与 s_recv 之前。

此外,请注意您的

if (len == -1 || len == 0 && errno != EAGAIN)

相同
if (len == -1 || (len == 0 && errno != EAGAIN) )

这没有意义,因为如果返回值不是-1,则必须忽略errno。如果返回值为0,那么对方已经关闭了连接。

更新:

我构建了一个简单的回显客户端

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=11
recv: Resource temporarily unavailable

如果我在循环之前移动 fcntl(O_NONBLOCK),一切正常。

因此,在读取或写入套接字之后摆弄非阻塞似乎是不可取的。

关于c - 当我打开 O_NONBLOCK 时,我得到 "0"和 "I/O error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14821100/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com