《socket编程由笑嘻嘻到绝望》(epoll简单高并发服务器模型)
2017-11-10 15:29
507 查看
在网络编程中相对使用select poll 机制 ,epoll具有着很大的优势,具体优势很多文章都有讲,在这里就不再赘述了。
在下面的例子中服务直接使用命令make就可以编译,运行命令demo:
测试的客户端运行命令demo:
主要用于学习epoll的使用,看了一些优秀的博客,在后面的完善过程中,依然要看很多资料
在下面的例子中服务直接使用命令make就可以编译,运行命令demo:
./epoll_server 127.0.0.1 6666
测试的客户端运行命令demo:
gcc -o client client.c ./client 127.0.0.1 6666
首先写Makefile
Tar = epoll_server CC = gcc CFLAGS = -Wall -O -g SOURCES = $(wildcard *.c *.cpp) OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES))) $(Tar):$(OBJS) 4000 $(CC) $(CFLAGS) -o $@ $< $(OBJS):$(SOURCES) $(CC) $(CFLAGS) -c $< -o $@ clean: rm -rf *.o $(Tar)
简单的服务器模型搭建,作用主要练习epoll的使用
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <strings.h> #include <stdlib.h> #include <sys/epoll.h> #include <unistd.h> #define MAXFD 10 #define BUFSIZE 512 int main(int argc,char*argv[]) { int socketfd = 0; int socket_flag = 0; int connfd = 0; int epfd = 0; int waitFd = 0; int i = 0; int n = 0; char recvBuf[BUFSIZE] = {}; char sendBuf[BUFSIZE] = "I am Baiyu"; struct sockaddr_in server_sock_addr; struct sockaddr_in client_sock_addr; struct epoll_event ev; struct epoll_event events[20]; if(argc != 3) { printf("Usage:%s error\nPlease input ./aout ip port\n",argv[0]); return -1; } socketfd = socket(AF_INET,SOCK_STREAM,0); if(-1 == socketfd){ printf("socketfd error!\n"); return -1; } epfd=epoll_create(256); ev.data.fd = socketfd; ev.events=EPOLLIN|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_ADD,socketfd,&ev); server_sock_addr.sin_family = AF_INET; server_sock_addr.sin_port = htons(atoi(argv[2])); server_sock_addr.sin_addr.s_addr = inet_addr(argv[1]); bzero(&(server_sock_addr.sin_zero), 8); if(-1 == bind(socketfd,(struct sockaddr*)&server_sock_addr,sizeof(struct sockaddr))){ printf("bind error!\n"); return -1; } if(-1 == listen(socketfd, MAXFD) ){ printf("listen error!"); return -1; } for(;;){ waitFd = epoll_wait(epfd,events,256,100); for(i=0;i<=waitFd;i++){ //新的连接 if(events[i].data.fd == socketfd){ socklen_t length = sizeof(struct sockaddr_in); connfd = accept(socketfd,(struct sockaddr *)&client_sock_addr, &length); if(connfd<0){ perror("connfd<0"); exit(1); } char *str = inet_ntoa(client_sock_addr.sin_addr); printf("New IP:%s\n",str); ev.data.fd=connfd; ev.events=EPOLLIN|EPOLLET; //注册 epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } //读操作 else if(events[i].events == EPOLLIN){ if ( (socket_flag = events[i].data.fd) < 0){ continue; } if ( (n = read(socket_flag, recvBuf, BUFSIZE)) < 0) { close(socket_flag); events[i].data.fd = -1; } else if (n == 0) { close(socket_flag); events[i].data.fd = -1; } printf("read:%s\n",recvBuf); ev.data.fd=socket_flag; ev.events=EPOLLOUT|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD,socket_flag,&ev); } //写操作 else if(events[i].events == EPOLLOUT){ socket_flag = events[i].data.fd; write(socket_flag, sendBuf, BUFSIZE); ev.data.fd=socket_flag; ev.events=EPOLLIN|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD,socket_flag,&ev); } } } return 0; }
测试客户端
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 6666 //>1024 <65535 #define MAXDATASIZE 1024 int main(int argc, char *argv[]) { int sockfd = 0; int numsize = 0; char buf[MAXDATASIZE]; struct hostent *input_ip; struct sockaddr_in client_addr; if (argc != 3) { printf("usage: client error\n"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("socket error\n"); exit(1); } if ((input_ip=gethostbyname(argv[1])) == NULL) { printf("gethostbyname error\n"); exit(1); } client_addr.sin_family = AF_INET; client_addr.sin_port = htons(atoi(argv[2])); client_addr.sin_addr = *((struct in_addr *)input_ip->h_addr); bzero(&(client_addr.sin_zero), 8); if(connect(sockfd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1) { printf("connect error\n"); exit(1); } write(sockfd, "12345678\r\n", 20) ; if((numsize=read(sockfd, buf, sizeof buf - 1)) == -1) { printf("recv error\n"); exit(1); } printf("%s\n",buf); fflush(stdout); close(sockfd); return 0; }
主要用于学习epoll的使用,看了一些优秀的博客,在后面的完善过程中,依然要看很多资料
相关文章推荐
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
- 并发服务器系列】3 epoll模型 - 邓维 - 博客园
- C++ linux epoll并发服务器模型初探
- 几种并发服务器模型的实现:多线程,多进程,select,poll,epoll
- Linux Socket 事件触发模型 epoll 示例 这里会写一个用C语言的TCP服务器的完全实现的简单程序
- 几种并发服务器模型的实现:多线程,多进程,select,poll,epoll - rail
- 几种并发服务器模型的实现:多线程,多进程,select,poll,epoll
- 【并发服务器系列】3 epoll模型
- 高并发服务器设计之多路复用模型
- Linux网络编程——tcp并发服务器(epoll实现)
- 多路转接-EPOLL 及简单的EPOLL服务器实现
- 聊聊Linux fork多进程并发服务器模型
- java 简单的文件上传下载服务器模型(IO + 多线程)
- C++ 网络编程 阻塞I/O模型并发回显服务器
- linux下epoll模型accept并发问题
- 简单的Boost::asio 高性能C/S服务器模型
- 基于的epoll模型的简单http服务器
- UNP学习笔记二--简单的并发服务器(concurrent servers)