mirror of https://github.com/F-Stack/f-stack.git
Example: fix listen queue overflow.
According to the FreeBSD Manual Page: - When kevent() returns and if `flags` is EVFILT_READ, sockets which have previously been passed to listen() return when there is an incoming connection pending. `data` contains the size of the listen backlog. So if an EVFILT_READ event reaches and it is the listen socket, we must accept `event->data` times. And for `ff_epoll` interface, we should continue to accept until it fails. In the previous version, we only accept once when event reaches, it will cause listen queue overflow.
This commit is contained in:
parent
c4e752fc00
commit
b2dbf8fd04
|
@ -66,38 +66,34 @@ int loop(void *arg)
|
||||||
|
|
||||||
/* Handle disconnect */
|
/* Handle disconnect */
|
||||||
if (event.flags & EV_EOF) {
|
if (event.flags & EV_EOF) {
|
||||||
|
|
||||||
/* Simply close socket */
|
/* Simply close socket */
|
||||||
ff_close(clientfd);
|
ff_close(clientfd);
|
||||||
|
|
||||||
//printf("A client has left the server...,fd:%d\n", clientfd);
|
|
||||||
} else if (clientfd == sockfd) {
|
} else if (clientfd == sockfd) {
|
||||||
|
int available = (int)event.data;
|
||||||
|
do {
|
||||||
int nclientfd = ff_accept(sockfd, NULL, NULL);
|
int nclientfd = ff_accept(sockfd, NULL, NULL);
|
||||||
if (nclientfd < 0) {
|
if (nclientfd < 0) {
|
||||||
printf("ff_accept failed:%d, %s\n", errno, strerror(errno));
|
printf("ff_accept failed:%d, %s\n", errno,
|
||||||
continue;
|
strerror(errno));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add to event list */
|
/* Add to event list */
|
||||||
kevSet.data = 0;
|
EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||||
kevSet.fflags = 0;
|
|
||||||
kevSet.filter = EVFILT_READ;
|
|
||||||
kevSet.flags = EV_ADD;
|
|
||||||
kevSet.ident = nclientfd;
|
|
||||||
kevSet.udata = NULL;
|
|
||||||
|
|
||||||
assert(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) == 0);
|
if(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) {
|
||||||
|
printf("ff_kevent error:%d, %s\n", errno,
|
||||||
//printf("A new client connected to the server..., fd:%d\n", nclientfd);
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
available--;
|
||||||
|
} while (available);
|
||||||
} else if (event.filter == EVFILT_READ) {
|
} else if (event.filter == EVFILT_READ) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
size_t readlen = ff_read(clientfd, buf, sizeof(buf));
|
size_t readlen = ff_read(clientfd, buf, sizeof(buf));
|
||||||
|
|
||||||
//printf("bytes %zu are available to read...,fd:%d\n", (size_t)event.data, clientfd);
|
|
||||||
|
|
||||||
ff_write(clientfd, html, sizeof(html));
|
ff_write(clientfd, html, sizeof(html));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
printf("unknown event: %8.8X\n", event.flags);
|
printf("unknown event: %8.8X\n", event.flags);
|
||||||
}
|
}
|
||||||
|
@ -133,12 +129,7 @@ int main(int argc, char * argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
kevSet.data = MAX_EVENTS;
|
EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
|
||||||
kevSet.fflags = 0;
|
|
||||||
kevSet.filter = EVFILT_READ;
|
|
||||||
kevSet.flags = EV_ADD;
|
|
||||||
kevSet.ident = sockfd;
|
|
||||||
kevSet.udata = NULL;
|
|
||||||
|
|
||||||
assert((kq = ff_kqueue()) > 0);
|
assert((kq = ff_kqueue()) > 0);
|
||||||
|
|
||||||
|
|
|
@ -65,33 +65,34 @@ int loop(void *arg)
|
||||||
for (i = 0; i < nevents; ++i) {
|
for (i = 0; i < nevents; ++i) {
|
||||||
/* Handle new connect */
|
/* Handle new connect */
|
||||||
if (events[i].data.fd == sockfd) {
|
if (events[i].data.fd == sockfd) {
|
||||||
|
while (1) {
|
||||||
int nclientfd = ff_accept(sockfd, NULL, NULL);
|
int nclientfd = ff_accept(sockfd, NULL, NULL);
|
||||||
if (nclientfd < 0) {
|
if (nclientfd < 0) {
|
||||||
printf("ff_accept failed:%d, %s\n", errno, strerror(errno));
|
break;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add to event list */
|
/* Add to event list */
|
||||||
ev.data.fd = nclientfd;
|
ev.data.fd = nclientfd;
|
||||||
ev.events = EPOLLIN;
|
ev.events = EPOLLIN;
|
||||||
assert(ff_epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) == 0);
|
if (ff_epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) != 0) {
|
||||||
//printf("A new client connected to the server..., fd:%d\n", nclientfd);
|
printf("ff_epoll_ctl failed:%d, %s\n", errno,
|
||||||
|
strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (events[i].events & EPOLLERR ) {
|
if (events[i].events & EPOLLERR ) {
|
||||||
/* Simply close socket */
|
/* Simply close socket */
|
||||||
ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
|
ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
|
||||||
ff_close(events[i].data.fd);
|
ff_close(events[i].data.fd);
|
||||||
//printf("A client has left the server...,fd:%d\n", events[i].data.fd);
|
|
||||||
} else if (events[i].events & EPOLLIN) {
|
} else if (events[i].events & EPOLLIN) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
size_t readlen = ff_read( events[i].data.fd, buf, sizeof(buf));
|
size_t readlen = ff_read( events[i].data.fd, buf, sizeof(buf));
|
||||||
//printf("bytes are available to read..., readlen:%d, fd:%d\n", readlen, events[i].data.fd);
|
|
||||||
if(readlen > 0) {
|
if(readlen > 0) {
|
||||||
ff_write( events[i].data.fd, html, sizeof(html));
|
ff_write( events[i].data.fd, html, sizeof(html));
|
||||||
} else {
|
} else {
|
||||||
ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
|
ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
|
||||||
ff_close( events[i].data.fd);
|
ff_close( events[i].data.fd);
|
||||||
//printf("A client has left the server...,fd:%d\n", events[i].data.fd);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("unknown event: %8.8X\n", events[i].events);
|
printf("unknown event: %8.8X\n", events[i].events);
|
||||||
|
|
Loading…
Reference in New Issue