您的位置:首页 > 编程语言

《socket编程由笑嘻嘻到绝望》(epoll简单高并发服务器模型)

2017-11-10 15:29 507 查看
在网络编程中相对使用select poll 机制 ,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的使用,看了一些优秀的博客,在后面的完善过程中,依然要看很多资料
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: