Слияние кода завершено, страница обновится автоматически
#include "iotcp.h"
static void client_in (fe_t *ptr);
static void client_hup(fe_t *ptr);
static void client_new(em_t*em, int fd);
void tcp_server(fe_t* fe)
{
int fd;
while (1) {
fd = accept(fe->fd, 0, 0);
if (fd < 0) {
if (errno != EAGAIN) perror("accept error");
return;
}
log_msg("server [%05d] accept ret: %d", fe->fd, fd);
client_new(fe->em, fd);
}
}
void domain_server(fe_t* fe)
{
int fd;
while (1) {
fd = unix_domain_accept(fe->fd, 0);
if (fd < 0) {
if (errno != EAGAIN) perror("unix_domain_accept error");
return;
}
log_msg("domain [%05d] accept ret: %d", fe->fd, fd);
client_new(fe->em, fd);
}
}
void client_new(em_t *em, int fd)
{
fe_t *fe = fe_new(em,fd);
fe_set(fe, EPOLLIN, client_in);
fe_set(fe, EPOLLHUP, client_hup);
fe_set(fe, EPOLLET, 0);
setfd_nonblock(fd);
fe_em_add(fe);
}
/*
man epoll
Q6
Will closing a file descriptor cause it to be removed from all epoll sets
automatically?
A6
Yes, but be aware of the following point. A file descriptor is a reference
to an open file description (see open(2)). Whenever a descriptor is dupli‐
cated via dup(2), dup2(2), fcntl(2) F_DUPFD, or fork(2), a new file
descriptor referring to the same open file description is created. An open
file description continues to exist until all file descriptors referring to
it have been closed. A file descriptor is removed from an epoll set only
after all the file descriptors referring to the underlying open file
description have been closed (or before if the descriptor is explicitly
removed using epoll_ctl(2) EPOLL_CTL_DEL). This means that even after a
file descriptor that is part of an epoll set has been closed, events may be
reported for that file descriptor if other file descriptors referring to
the same underlying file description remain open.
close(fd)时会自动调用epoll_ctl(EPOLL_CTL_DEL)从epoll中清理
如果 close(fd) 放在fd_del前面,就不需要再调用fd_del了
但是这里有个问题必须注意,当所有fd的引用都close时epoll才会自动清理
所以 为了不必要的麻烦,此处最好是明确的
通过 fe_del 调用 epoll_ctl 删除epoll事件监听
拒绝暗箱操作 偷懒可能酿成大祸 一切图省事的操作都可能造成副作用
Yuan Hong
*/
void client_out(fe_t *fe)
{
int fd = fe->fd;
fe_del(fe);
close(fd);
}
void client_hup(fe_t *fe)
{
log_msg("client %d client_hup", fe->fd);
client_out(fe);
}
void client_in(fe_t *fe)
{
int fd = fe->fd;
char buff[1024] = {0};
int n;
eintr:
while ((n = read(fd, buff, sizeof(buff))) > 0) {
// recv datas ....
log_msg("client [%05d] read len %d", fd, n);
}
if (n < 0) {
if (errno == EAGAIN) return;
if (errno == EINTR) goto eintr;
log_msg("client [%05d] read ret %d to error:%s", fd, n, strerror(errno));
client_out(fe);
}
if (n == 0) {
log_msg("client [%05d] read ret %d to close", fd, n);
client_out(fe);
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )