close并不是当即关闭一个链接,而是将fd的引用数减1。算法
#include<sys/sendfile.h> ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
#include<fcntl.h> ssize_t splice(int in_fd, loff_t* off_in, int out_fd, loff_t* off_out, size_t len, unsigned int flags); //使用splice实现零拷贝反射服务器 int pipefd[2]; int ret = pipe(pipefd); ret = splice(connectfd, NULL, pipefd[1], NULL, 65536, SPLICE_F_MORE | SPLICE_F_MOVE); ret = splice(pipefd[0], NULL, connectfd, NULL, 65536, SPLICE_F_MORE | SPLICE_F_MOVE); close(connectfd);
EPOLLONESHOT:对于注册EPOLLONESHOT事件的文件描述符,操做系统最多触发其上注册的一个事件(可读,可写或者异常),而且只触发一次,除非咱们使用epoll_ctl函数重置该文件描述符上注册的EPOLLONESHOT事件。
```编程
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);服务器
FD_ZERO(fd_set* fdset);
FD_SET(int fd, fd_set* fdset);
FD_CLR(int fd,fd_set* fdset);
int FD_ISSET(int fd,fd_set* fdset);网络
struct timeval
{
long tv_sec; //秒数
long tv_usec; //微秒数
}socket
int poll(struct pollfd* fds, nfds_t nfds, int timeout);函数
struct pollfd
{
int fd;
short event; //注册的事件
short revent; //实际发生的事件,内核填充,记得每次判断后归零
}ui
POLLIN:数据可读
POLLOUT:数据可写
POLLREHUP:TCP链接被对方关闭,或者对方关闭了写操做
POLLERR:错误
POLLHUP:挂起
POLLNVAL:文件描述符没有打开操作系统
int epoll_create(int size);
int epoll_ctl(int epollfd, int op, int fd, struct epoll_event* event);
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);线程
op参数的类型:
EPOLL_CTL_ADD:向事件注册表中注册fd事件
EPOLL_CTL_MOD:修改fd上注册的事件
EPOLL_CTL_DEL:删除fd上注册的事件ssr
struct epoll_event
{
_uint32_t events;
epoll_data_t data;
};
union epoll_data
{
void* ptr;
int fd; //指定事件所从属的描述符
uint32_t u32;
uint64_t u64;
} epoll_data_t;
- 服务器端处理信号的方式:
void sig_handler(int sig)
{
int save_errno = errno;
int msg = sig;
send(pipefd[1], (char*)&msg, 1, 0);
errno = save_errno;
}
void addsig(int sig)
{
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handleer = sig_handler;
sa.sa_flags |= SA_RESTART;
sigfillset(&sa.sa_mask);
assrt(sigaction(sig, &sa, NULL) != -1);
}
```