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
原创粉丝点击