for(int t=0;t<;physicalCoreCount;t++){
int-pid=fork();
如果(pid==0){
//建立epoll
epoll_fd=epoll_create1(0);
event.data.fd=listenSocketfd;
event.events=EPOLLIN | EPOLLET;
ret=epoll\u ctl(epoll\u fd、epoll\u ctl\u ADD、listenSocketfd和事件);
events=(epoll_event*)calloc(LISTENQ,sizeof(event));
//*****/
而(1){
int ndfs=epoll\u wait(epoll\u fd,events,curfdCount,-1);
如果(ndfs==-1){
持续
}
对于(int i=0;i<;ndfs;i++){
if(events[i].data.fd==listenSocketfd){//原始侦听器
int new_connfd=accept(事件[i].data.fd,(sockaddr*)和clientaddr,&;clientlen);
如果(新连接==-1){
if(errno==EAGAIN | | errno==ewoldblock){
持续
}
else ExitErrorLog(“接受()”);
}
设置非块(新连接);
event.events=EPOLLIN | EPOLLET;
event.data.fd=新连接;
if(epoll\u ctl(epoll\u fd、epoll\u ctl\u ADD、new\u connfd和&;event)<;0)
exitPerrorLog(“epoll”单元);
clientAddressOffd[new_connfd]=新的sockaddr_in();
memcpy(客户地址[new_connfd],&;ClientAddress,sizeof(客户地址));
curfdCount++;
}
否则{
进程(events[i].data.fd,clientAddressOffd[events[i].data.fd]);
//epoll\u ctl(epoll\u fd、epoll\u ctl\u DEL、事件[i].data.fd和&;event);
如果(curfdCount>;10000)curfdCount=10000;//curfdCount--;
}
}
}
}
}
出现此问题是因为我正在尝试实现持久连接(而不是在响应后关闭)。但是,子0可以()接受套接字文件描述符X,然后对其进行处理,但稍后子1可以()接受相同的文件描述符。由于我没有关闭子0上的连接(以实现HTTP1.1保持活动),现在有2个子对象正在读取/写入同一文件描述符
预防这个问题的方法是什么?多谢各位
编辑:重要更新:所以主要问题是,我认为两个相同的FD意味着它是相同的连接,我想避免这种情况,因为它会导致两个孩子读/写相同的东西。如果这种情况没有发生(读/写重叠),那么我认为问题已经解决了。有人能证实吗
您正在创建多个epoll实例,并在每个实例中的侦听套接字上注册边缘触发事件。当然,当一个新的连接可以接受时,您将从每个连接获得一个事件。但是,只有一个进程可以成功地接受每个连接。正如在注释中所观察到的,两个不同的子级可能接受在各自进程中分配了相同文件描述符编号的连接,但这并不意味着它们引用相同的套接字
您有几种选择,但其中最突出的是:
-
使用一个由所有进程共享的epoll实例。您可以通过让父级在分叉任何子级之前创建它来自动获得此信息。在这种情况下,每个边缘触发的事件只有一个子级接收。当然,如果孩子们打算注册只应由他们接收的活动,那么这将不会很好地起作用
-
只要接受(没有双关语)当连接可用时多个进程将接收事件,并处理它。这似乎就是您现在正在做的(通过忽略
EAGAIN和EWOULDBLOCK来自accept()的错误),我看不出您不应该继续这样做的具体原因