C 事件循环-套接字连接上的触发器

C 事件循环-套接字连接上的触发器,c,C,我试图学习更多关于事件循环的知识,并充分理解它,所以我尝试做一些基本的东西。我在Mac上,所以我使用的是kqueue 其思想是仅在新套接字连接上触发事件循环。事件循环在套接字连接时被触发,但不会在下一个周期停止。它在第一次连接后继续打印: NEW CLIENT NEW CLIENT NEW CLIENT NEW CLIENT NEW CLIENT 等等 它支持在新的套接字连接上只打印“新客户端” 以下是完整的源代码: #include <stdlib.h> #include <

我试图学习更多关于事件循环的知识,并充分理解它,所以我尝试做一些基本的东西。我在Mac上,所以我使用的是kqueue

其思想是仅在新套接字连接上触发事件循环。事件循环在套接字连接时被触发,但不会在下一个周期停止。它在第一次连接后继续打印:

NEW CLIENT
NEW CLIENT
NEW CLIENT
NEW CLIENT
NEW CLIENT
等等

它支持在新的套接字连接上只打印“新客户端”

以下是完整的源代码:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <errno.h>


struct kevent e;
static struct sockaddr_in server;
static int server_fd, queue;


static void event_server_listen (int port) {
    int err, flags;

    queue = kqueue();

    server_fd = socket(AF_INET, SOCK_STREAM, 0);


    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    int opt_val = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));

    err = bind(server_fd, (struct sockaddr *) &server, sizeof(server));

    flags = fcntl(server_fd, F_GETFL, 0);


    err = fcntl(server_fd, F_SETFL, flags | O_NONBLOCK);


    err = listen(server_fd, SOMAXCONN);

}


static void event_change (int ident, int filter, int flags, void *udata) {

    e.ident = ident;
    e.filter = filter;
    e.flags = flags;
    e.fflags = 0;
    e.data = 0;
    e.udata = udata;
}

static void event_loop () {

    while (1) {


        int nev = kevent(queue, &e, 1, &e, 1, NULL);

        if (nev == -1) { exit(0); }


        printf("NEW CLIENT\n");


    }
}





int main (int argc, char *argv[]) {


    int port = 8899;

    event_server_listen(port);
    event_change(server_fd, EVFILT_READ, EV_ADD | EV_ENABLE, NULL);
    event_loop();

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构kevent e;
服务器中的静态结构sockaddr_;
静态int-server_-fd,队列;
静态无效事件\u服务器\u侦听(int端口){
INTERR,标志;
queue=kqueue();
服务器\u fd=socket(AF\u INET,SOCK\u STREAM,0);
server.sinu family=AF\u INET;
server.sin_port=htons(端口);
server.sin_addr.s_addr=htonl(INADDR_ANY);
int opt_val=1;
setsockopt(服务器fd、SOL_套接字、SO_REUSEADDR和opt_val、sizeof(opt_val));
err=bind(server_fd,(struct sockaddr*)&server,sizeof(server));
flags=fcntl(server\u fd,F\u GETFL,0);
err=fcntl(服务器fd、F设置FL、标志O非块);
err=listen(服务器\u fd,SOMAXCONN);
}
静态无效事件_更改(int ident、int filter、int标志、void*udata){
e、 ident=ident;
e、 过滤器=过滤器;
e、 旗帜=旗帜;
e、 fflags=0;
e、 数据=0;
e、 udata=udata;
}
静态无效事件\u循环(){
而(1){
int nev=kevent(队列,&e,1,&e,1,NULL);
如果(nev==-1){exit(0);}
printf(“新客户端”);
}
}
int main(int argc,char*argv[]){
int端口=8899;
事件\服务器\侦听(端口);
事件更改(服务器fd、EVFILT读取、EV添加、EV启用、NULL);
事件_循环();
返回0;
}

有人能解释一下为什么会发生这种情况,并告诉我如何修复它吗

为什么保存
err
值,但从不使用它做任何事情?您是否删除了处理错误的行?保留它们,它们不会打扰我们。是的,我删除了以不发布大型代码:-),这样我们就可以集中精力解决这个问题,您永远不会调用
socket上的
accept()
来完成新连接的建立,因此套接字始终显示为可读的,因为它有一个挂起的连接。Shawn!有意义的是:D-e.udata最包含accept函数吗?您可以演示如何从添加到@Shawn的事件循环中提取它吗?如果您使用了,那么您可以在
accept()
和套接字可读时进行区分。我在过去实施过这样的活动系统。