epoll池用法
来源:互联网 发布:数据分析建模 编辑:程序博客网 时间:2024/05/20 20:45
声明:本博文用于学习总结及工作心得
解决高并发, 替代线程方式,但是效率不及线程
代码:
main#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>#include <sys/epoll.h>#include <fcntl.h>int main(int arg, char *args[]){if(arg < 2){return -1;}int iport = atoi(args[1]);int listen_st = socket_create(iport);if(listen_st == 0){return -1;}//声明epoll_event结构体变量,ev用于注册事件,数组用于回传要处理的事件struct epoll_event ev,events[100];//生成用于处理accept的epoll专用的文件描述符int epfd = epoll_create(100);//把socket设置为非阻塞方式setnonblocking(listen_st);ev.data.fd = listen_st;//设置要处理的事件相关文件描述符ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;//设置要处理的事件类型epoll_ctl(epfd, EPOLL_CTL_ADD, listen_st, &ev);//注册epoll事件int st = 0;while(1){int nfds = epoll_wait(epfd, events, 100, -1);if(nfds == -1){printf("epoll_wait failed %s\n", strerror(errno));break;}int i = 0;for(i =0; i< nfds; i++){if(events[i].data.fd < 0){continue;}if(events[i].data.fd == listen_st){st = scoket_accept(listen_st);if(st >= 0){setnonblocking(st);ev.data.fd = st;ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;//设置要处理的事件类型epoll_ctl(epfd, EPOLL_CTL_ADD, st, &ev);continue;}}//client端的socket有事件到达if(events[i].events & EPOLLIN) //socket收到数据{st = events[i].data.fd;if(socket_recv(st) <=0){close(st);events[i].data.fd = -1;}}if(events[i].events & EPOLLERR)//socket 错误{st = events[i].data.fd;close(st);events[i].data.fd = -1;}if(events[i].events & EPOLLHUP)//socket关闭{st = events[i].data.fd;close(st);events[i].data.fd = -1;}}}close(epfd);return EXIT_SUCCESS;}
创建socketint socket_create(int port){int st = socket(AF_INET, SOCK_STREAM, 0);int on =0;if(setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){printf("setsockopt failed %s\n", strerror(errno));return 0;}struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(st, (struct sockaddr *)&addr, sizeof(addr)) == -1){printf("bind port %d failed %s\n", port, strerror(errno));return 0;}if(listen(st, 300) == -1){printf("listen failed %s\n", strerror(errno));return 0;}return st;}
连接client端int scoket_accept(int listen_st){struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);memset(&client_addr, 0, sizeof(client_addr));int client_st = accept(listen_st,(struct sockaddr *)&client_addr, &len);if(client_st < 0){printf("accept failed %s\n", strerror(errno));}else{printf("accept by %s\n", inet_ntoa(client_addr.sin_addr));}return client_st;}
收发消息ssize_t socket_recv(int st){char buf[1024];memset(buf, 0, sizeof(buf));ssize_t rc = recv(st, buf, sizeof(buf), 0);if(rc <= 0){printf("recv failed %s\n", strerror(errno));}else{printf("recv %s\n", buf);send(st, buf, rc, 0);}return rc;}
设置socket非阻塞方式void setnonblocking(int st){int opts = fcntl(st, F_GETFL);if(opts < 0){printf("fcntl failed %s\n", strerror(errno));}opts = opts | O_NONBLOCK;if(fcntl(st, F_SETFL, opts) < 0){printf("fcntl failed %s\n", strerror(errno));}}
makefile:
.SUFFIXES:.c .oCC=gccSRCS=epoll.cOBJS=$(SRCS:.c=.o)EXEC=epollstart: $(OBJS)$(CC) -o $(EXEC) $(OBJS)@echo '-----------OK-----------'.c.o:$(CC) -Wall -g -o $@ -c $<clean:rm -rf $(OBJS)
0 0
- epoll池用法
- epoll用法
- epoll用法
- epoll用法说明(源代码)
- epoll用法举例说明
- select,poll,epoll用法
- epoll用法介绍
- linux epoll用法
- select,poll,epoll用法
- select,poll,epoll用法
- epoll用法介绍
- epoll用法【整理】
- linux epoll的用法
- epoll用法整理
- select,poll,epoll用法
- epoll用法详解 优点
- select,poll,epoll用法
- Linux epoll 用法
- Android开发 — 实现手指从屏幕底部向上滑动的方式来显示Dialog(可为实现自由拖动Dialog提供参考)
- 初探cmake
- app移动接口开发需要注意什么
- 欢迎使用CSDN-markdown编辑器
- 在屏幕上输出一个菱形
- epoll池用法
- Spring Bean装配之Spring对JSR支持的说明
- QT-常见错误总结
- java设计模式之工厂方法探究
- java.net.BindException: Address already in use: JVM_Bind错误解决办法
- linux-挂载新分区
- VLC介绍以及库的使用
- 下划线转驼峰,3种实现方式效率对比
- 【Get深一度】小波分析概念3——正则性是什么意思,通俗解释