- 1、函数介绍
- 2、使用
- 3、socket常用函数出错处理封装
1.1、创建一颗树,返回值指向树的根节点
#includeint epoll_create(int size); 参数: size 创建的红黑树的监听数据节点(数目最大有多大,从Linux 2.6.8开始,max_size参数将被忽略,但必须大于零。) 返回值: 成功 指向新创建的红黑树的根节点fd 失败 -1 errno
1.2、对树进行操作(增加,修改,删除)节点
int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event);
参数:
epfd: epoll_create 函数的返回值
op: 对该监听的红黑树操作
EPOLL_CTL_ADD 添加fd到 监听红黑树
EPOLL_CTL_MOD 修改fd在监听红黑树上的监听事件
EPOLL_CTL_DEL 将一个fd从监听红黑树上摘下(取消监听)
fd:待监听的fd
event:结构体的地址
struct epoll_event {
uint32_t events;
// EPOLLIN / EPOLLOUT / EPOLLERR
epoll_data_t data;
// fd 对应监听事件的fd
// void* ptr
// u32
// u64
};
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
返回值:
成功 0
失败 -1 errno
1.3、阻塞监听树上面节点的请求,将请求返回到数组中
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
参数:
epfd:epoll_create 函数返回值 epfd
events:传出参数【数组】,满足监听条件的
maxevents:数组 元素的总个数1024
timeout:毫秒
-1 阻塞
0 不阻塞
>0 超时事件(毫秒)
返回值:
>0 满足监听的总个数,可以用作循环上限
0 没有fd满足条件
-1 errno
2、使用
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "socket_wrap.h" #define OPEN_MAX 1024 int main() { int i,listenfd,connfd,sockfd,j; int n,num = 0; ssize_t nready,efd,res; char buf[1024],str[INET_ADDRSTRLEN]; socklen_t clilen; struct sockaddr_in cliaddr,servaddr; struct epoll_event tep,ep[OPEN_MAX]; listenfd = Socket(AF_INET,SOCK_STREAM,0); int opt = 0; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9999); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); Bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); Listen(listenfd,128); efd = epoll_create(OPEN_MAX); if(efd == -1) perr_exit("epoll _create error"); tep.events = EPOLLIN; tep.data.fd = listenfd; res = epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep); if(res == -1) perr_exit("epoll_ctl error"); while (1) { nready = epoll_wait(efd,ep,OPEN_MAX,-1); if(nready == -1) perr_exit("epoll_wait error"); for(i=0;i 3、socket常用函数出错处理封装 socket_wrap.h
#ifndef __WRAP_H_ #define __WRAP_H_ void perr_exit(const char* s); int Accept(int fd,struct sockaddr* sa,socklen_t* salenptr); int Bind(int fd,const struct sockaddr* sa,socklen_t salen); int Connect(int fd,const struct sockaddr* sa,socklen_t salen); int Listen(int fd,int backlog); int Socket(int family,int type,int protocol); ssize_t Read(int fd,void* ptr,size_t nbytes); ssize_t Write(int fd,const void* ptr,size_t nbytes); int Close(int fd); ssize_t Readn(int fd,void* vptr,size_t n); ssize_t Writen(int fd,const void* vptr,size_t n); static ssize_t my_read(int fd,char* ptr); ssize_t Readline(int fd,void* vptr,size_t maxlen); #endif // !__WRAP_H_socket_wrap.c
#include#include #include #include #include #include #include #include #include #include "socket_wrap.h" void perr_exit(const char* s) { perror(s); exit(1); } int Accept(int fd,struct sockaddr* sa,socklen_t* salenptr) { int n; again: if((n=accept(fd,sa,salenptr))<0) { if(errno == EConNABORTED || (errno==EINTR)) goto again; else perr_exit("accept error"); } return n; } int Bind(int fd,const struct sockaddr* sa,socklen_t salen) { int n; if((n=bind(fd,sa,salen))<0) { perr_exit("bind error"); } return n; } int Connect(int fd,const struct sockaddr* sa,socklen_t salen) { int n; if((n=connect(fd,sa,salen))<0) perr_exit("connect error"); return n; } int Listen(int fd,int backlog) { int n; if((n=listen(fd,n))<0) { perr_exit("listen error"); } return n; } int Socket(int family,int type,int protocol) { int n; if((n=socket(family,type,protocol))<0) perr_exit("socket error"); return n; } ssize_t Read(int fd,void* ptr,size_t nbytes) { ssize_t n; again: if((n=read(fd,ptr,nbytes))<0) { if(errno==EINTR) goto again; else return -1; } return n; } ssize_t Write(int fd,const void* ptr,size_t nbytes) { ssize_t n; if((n=write(fd,ptr,nbytes))<0) perr_exit("write error"); return n; } int Close(int fd) { int n; if((n=close(fd))<0) perr_exit("close error"); return n; } ssize_t Readn(int fd,void* vptr,size_t n) { size_t nleft; // unsigned int 剩余未读取字节数 ssize_t nread; // int 实际读到的字节数 char* ptr; ptr = vptr; nleft = n; while (nleft>0) { if((nread = read(fd,ptr,nleft))<0) { if(errno == EINTR) nread = 0; else return -1; } else if(nread == 0) break; nleft -= nread; ptr+=nread; } return n-nread; } ssize_t Writen(int fd,const void* vptr,size_t n) { size_t nleft; ssize_t nwritten; const char* ptr; ptr = vptr; nleft = n; while(nleft>0) { if((nwritten=write(fd,ptr,nleft))<=0) { if(nwritten<0 && errno==EINTR) nwritten = 0; else return -1; } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd,char* ptr) { static int read_cnt; static char* read_ptr; static char read_buf[100]; if(read_cnt<=0) { again: if((read_cnt=read(fd,read_buf,sizeof(read_buf)))<0) { if(errno == EINTR) goto again; return -1; } else if(read_cnt == 0) return 0; read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } // 传出参数 vptr ssize_t Readline(int fd,void* vptr,size_t maxlen) { ssize_t n,rc; char c,*ptr; ptr = vptr; for(n=1;n



