I/O多路转接(三)——epoll函数
来源:互联网 发布:中企动力域名到期 编辑:程序博客网 时间:2024/05/16 12:52
I/O多路转接(三)——epoll函数
第三篇介绍epoll函数。
介绍先略过,还在整理当中,先贴代码。
使用epoll LT与ET模式的网路服务器
LT
这是一个简单的服务器,三次握手后只完成一次读写就关闭连接。通过浏览器发送一个HTTP请求,服务器传回HELLO EPOLL消息。
server.c
#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/stat.h>#include<stdlib.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/epoll.h>const char *msg = "HTTP/1.1 200 OK\r\n\r\n<html><h1>Hello epoll!</h1></html>";int startup(char*ip,int port){ int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0){ perror("socket"); return 2; } int opt = 1; setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = inet_addr(ip); if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){ perror("bind"); return 3; } if(listen(sock,10) < 0){ perror("listen"); return 4; } return sock;}int main(int argc,char *argv[]){ if(argc!= 3){ printf("Usage:%s [ip] [port]\n",argv[0]); return 1; } int listen_sock = startup(argv[1],atoi(argv[2])); printf("listen_sock has been created,the value is %d\n",listen_sock); //监听套接字创建完成. int epfd = epoll_create(256);//创建epoll模型,返回一个epoll模型句柄。 if(epfd < 0){ perror("epoll_create"); return 5; } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = listen_sock; epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev);//将listen_sock添加到rb_tree; int nums = -1; int timeout = 1000; struct epoll_event revs[64];//epoll事件集 int size = 64; while(1){ nums = epoll_wait(epfd,revs,size,-1); switch(nums){ case 0: printf("timeout\n"); break; case -1: perror("epoll_wait"); break; default: { //已经有事件就绪。 int i= 0; for(;i < nums;i++){ int fd = revs[i].data.fd; if(fd==listen_sock&&revs[i].events&EPOLLIN{ //listen_sock读事件已经就绪。 struct sockaddr_in client; socklen_t len = sizeof(client); int new_sock = accept(listen_sock,(struct sockaddr*)&client,&len); if(new_sock < 0){ perror("accept"); continue; } printf("get a client!ip:%s,port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); //将CLIENT的socket添加到epoll中 ev.events = EPOLLIN; ev.data.fd = new_sock; epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&ev); }else if(fd!= listen_sock){//其他关心描述符状态改变。 if(revs[i].events&EPOLLIN){ char buf[4096]; ssize_t s = read(fd,buf,sizeof(buf)-1); if(s >0){ buf[s]= 0; printf("client say# %s\n",buf); ev.events = EPOLLOUT;//读后关心这个fd的写事件。 ev.data.fd = fd; epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev); }else if(s==0){ printf("client is quit!\n"); close(fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL); }else{ perror("read"); close(fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL); } }else if(revs[i].events&EPOLLOUT){ write(fd,msg,strlen(msg)); close(fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL); } } } } break; } }
使用epoll ET模式的网路服务器
#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/stat.h>#include<stdlib.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/epoll.h>#include<errno.h>#include<fcntl.h>const char *msg = "HTTP/1.1 200 OK\r\n\r\n<html><h1>Hello epoll!</h1></html>";struct epoll_event ev;#define SIZE 64typedef struct fd_buff{ int fd; char buf[SIZE]; int size;}fdbuff,*fdbuff_p;void* alloc_buff(int fd){ fdbuff_p tmp =(fdbuff_p)malloc(sizeof(fdbuff)); if(!tmp){ perror("malloc"); return NULL; } tmp->fd = fd; tmp->size = SIZE; return tmp;}int startup(char*ip,int port){ int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0){ perror("socket"); return 2; } int opt = 1; setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = inet_addr(ip); if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){ perror("bind"); return 3; } if(listen(sock,10) < 0){ perror("listen"); return 4; } return sock;} void set_nonblock(int fd)//设置套接字为非阻塞。{ int fl = fcntl(fd, F_GETFL);//拿到当前套接字状态保存到fl fcntl(fd,F_SETFL,fl|O_NONBLOCK);//设置为非阻塞态}int myread(int fd, char buf[],int size){ ssize_t len = 0; ssize_t total = 0; int count = 0; while((len = read(fd,buf+total,100))> 0){ count++; total += len; printf("read %d!msg:%s total = %d\n",count,buf,total); } if(len < 0||errno== EAGAIN) printf("read done! total = %d\n",total); else if(len==0) return 0; else return -1; return total;}int mywrite(int fd, char buf[],int size){ ssize_t len = 0; ssize_t total = 0; int count = 0; while(1){ len = write(fd,buf+total,strlen(buf+total)); if(len > 0) total += len; if(len < 0||errno== EAGAIN){ printf("write done! total = %d\n",total); break; } } return total;}int myaccept(int listen_sock,int epfd){ struct sockaddr_in client; socklen_t len = sizeof(client); int new_sock = 0; int count = 0; while(( new_sock = accept(listen_sock,(struct sockaddr*)&client,&len))>0){ count++; printf("get a client!ip:%s,port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); //将CLIENT的socket添加到epoll中 ev.events = EPOLLIN|EPOLLET; set_nonblock(new_sock); ev.data.ptr = alloc_buff(new_sock); epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&ev); } if(new_sock < 0&&errno==EAGAIN){ printf("server has accept all client,count= %d\n",count); }}void del_buff(fdbuff_p p){ if(p!=NULL) free(p);}int main(int argc,char *argv[]){ if(argc!= 3){ printf("Usage:%s [ip] [port]\n",argv[0]); return 1; } int listen_sock = startup(argv[1],atoi(argv[2])); set_nonblock(listen_sock); printf("listen_sock has been created,the value is %d\n",listen_sock); //监听套接字创建完成. int epfd = epoll_create(256);//创建epoll模型,返回一个epoll模型句柄。 if(epfd < 0){ perror("epoll_create"); return 5; } ev.events = EPOLLIN|EPOLLET; ev.data.ptr =alloc_buff(listen_sock); epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev);//将listen_sock添加到rb_tree; int nums = -1; int timeout = 1000; struct epoll_event revs[64];//epoll事件集 int size = 64; while(1){ nums = epoll_wait(epfd,revs,size,-1); switch(nums){ case 0: printf("timeout\n"); break; case -1: perror("epoll_wait"); break; default: { //已经有事件就绪。 int i= 0; for(;i < nums;i++){ fdbuff_p fp =(fdbuff_p)revs[i].data.ptr; if(fp->fd == listen_sock&&revs[i].events&EPOLLIN ){//listen_sock读事件已经就绪。 myaccept(listen_sock, epfd); }else if(fp->fd!= listen_sock){//其他关心描述符状态改变。 if(revs[i].events&EPOLLIN){ ssize_t s = myread(fp->fd,fp->buf,fp->size); if(s >0){ fp->buf[s]=0; printf("client say# %s\n",fp->buf); ev.events = EPOLLOUT|EPOLLET;//读后关心这个fd的写事件。 ev.data.ptr = fp; epoll_ctl(epfd,EPOLL_CTL_MOD,fp->fd,&ev); }else if(s==0){ printf("client is quit!\n"); close(fp->fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL); del_buff(fp); }else{ perror("read"); close(fp->fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL); del_buff(fp); } }else if(revs[i].events&EPOLLOUT){ mywrite(fp->fd,fp->buf,fp->size); close(fp->fd); epoll_ctl(epfd,EPOLL_CTL_DEL,fp->fd,NULL); //del_buff(fp); } } } } break; } } return 0;}
阅读全文
0 0
- I/O多路转接(三)——epoll函数
- Linux—I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- I/O多路转接之epoll
- 【Linux】I/O多路转接epoll
- I/O多路转接之epoll
- I/O多路转接-----epoll服务器
- I/O多路转接之epoll
- ]I/O多路转接(二)之epoll服务器
- epoll服务器---I/O多路转接之epoll
- Linux【网络编程】——I/O多路转接之epoll服务器
- 多路复用 I/O 多路转接 select / poll / epoll
- I/O多路转接---epoll的笔记
- 常见排序算法整理(三)----归并排序、快速排序
- Java NIO流--二
- Linux shell脚本的字符串截取
- 常用开发git指令总结 欢迎补充
- Catch That Cow
- I/O多路转接(三)——epoll函数
- XYNU OJ 1091: 习题6-3 求整型矩阵对角线元素之和
- Python目录遍历的三种方式
- 51Nod 1282 时钟 —— 最小表示法 + 字符串哈希
- 独木舟上的旅行
- shiro框架初步学习
- Android开发 之 浮窗
- 03 Ext js学习之初识Maven
- 如何用手机访问电脑本地localhost网页, 以调试项目?