最近一直在做服务器的开发,网络部分选用epoll模型来开发,总结些经验如下:
man中给出的例子是
for(;;) {
nfds = epoll_wait(kdpfd, events, maxevents, -1);
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) {
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
fprintf(stderr, "epoll set insertion error: fd=%d/n",
client);
return -1;
}
}
else
do_use_fd(events[n].data.fd);
}
}
但是这个例子要直接放到项目中会有一些问题,首先做高并发的游戏服务器要考虑到短时间的客户端并发连接过来,所以accept这个函数调用必须要改成一个循环调用。另外这个例子只给出了accept后可以读数据,写数据并没有给出。
我的做法是再开一个ie线程来专门发送数据。
补充说明下, 之所以accept的用循环来调用接收,是因为可能在很短暂的时间内有大量的连接过来,而我们这里我们的epoll用的是 ET 模式来监视listener这个端口的,有事件到来,只会通知一次。循环结束条件是accept 返回错误并且errno == EAGAIN
同样要注意的地方是do_use_fd(events[n].data.fd); 这个函数里面的recv函数也要注意循环的调用,知道errno == EAGAIN 为止!