gpt4 book ai didi

c - 非阻塞连接不会向 kqueue 报告完成情况

转载 作者:行者123 更新时间:2023-11-30 16:20:25 24 4
gpt4 key购买 nike

在 MacOS 中,我使用 O_NONBLOCK 设置了一个读+写套接字来连接到远程服务器。我使用 kqueue 来等待和协调 I/O 事件。对 connect() 的调用立即触发 EINPROGRESS,这是理所应当的。很快,连接就完成了。这是通过从服务器接收数据来确认的。

但是,我认为当连接最终完成并变得可写时,kqueue 会返回一个 kevent 吗?没有这样的事件到来。 connect() 的手册页指出:

[EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately. It is possible to select(2) for completion by selecting the socket for writing.

(1) 这是否意味着我需要使用 select() 而不是 kqueque 来接收连接完成的通知?

(2) 顺便说一句,如果我尝试连接到端口上没有任何内容监听的服务器,那么 kevent 很快就会返回 EOF 来报告那里没有任何内容。

(3) 如果我尝试连接到不存在的 IP,那么我的 kevent 在我设置的超时时间(15 秒)后就会超时。

代码如下。编译,启动一个“服务器”,例如nc -l 10000,运行带或不带IP地址参数的程序,它将分别远程或本地连接。

#include <sys/event.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
}

int fcntl_flags = fcntl(fd, F_GETFL);
if (fcntl_flags < 0) {
perror("fcntl");
}

fcntl_flags = fcntl(fd, F_SETFL, fcntl_flags | O_NONBLOCK);
if (fcntl_flags < 0) {
perror("fcntl");
}

struct sockaddr_in addr_in;
memset(&addr_in, 0, sizeof addr_in);
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(10000);
if (!inet_pton(AF_INET, argc > 1 ? argv[1] : "127.0.0.1", &addr_in.sin_addr)) {
perror("inet_aton");
exit(EXIT_FAILURE);
}

struct kevent change;
struct kevent event;

// Create kqueue
int kq;
if ((kq = kqueue()) < 0) {
perror("kqueue");
}

// Set read and write on socket
EV_SET(&change, fd, EVFILT_READ | EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, NULL);

// Put socket in kqueue, return immediately
struct timespec tmout = { 0, 0 };
int nev = kevent(kq, &change, 1, &event, 1, &tmout);
printf("Number events: %d (should be 0)\n", nev);

// Connect socket to server
if (!connect(fd, (struct sockaddr *) &addr_in, sizeof(struct sockaddr))) {
printf("Connected\n");
}
else if (errno == EINPROGRESS) {
printf("EINPROGRESS\n");
}

// Wait for connection to complete
tmout.tv_sec = 15;
nev = kevent(kq, &change, 0, &event, 1, &tmout);

if (nev) {
printf("Number events: %d, filter: %x, flags: %x, data: %ld\n", nev, event.filter, event.flags, event.data);
}
else {
printf("Timeout\n");
}

return 0;
}

最佳答案

想通了。

EVFILT_READ == ffffffff

EVFILT_WRITE == fffffffe

这使得 EVFILT_READ | EVFILT_WRITE == EVFILT_READ

结果是“或”将它们组合在一起使 kqueue 仅等待 READ 事件。标志可以是“或”,但过滤器不应该。

关于c - 非阻塞连接不会向 kqueue 报告完成情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55319444/

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