linux-----网络编程----epoll实现并发服务器

/*************************************************************************
    > File Name: epoll_serve.c
    > Author: xuhcen_allen
    > Mail: [email protected] 
    > Created Time: 2019年02月14日 星期四 09时08分16秒
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<sys/epoll.h>
#include<stdlib.h>

#define PORT 8080

int main()
{
	struct sockaddr_in serv_addr,cli_addr;
	socklen_t serv_len = sizeof(serv_addr);
	socklen_t cli_len = sizeof(cli_addr);

	//创建监听套接字:
	int lfd = socket(AF_INET,SOCK_STREAM,0);
	memset(&serv_addr,0,serv_len);
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port=htons(PORT);

	//绑定IP和端口:
	bind(lfd,(struct sockaddr*)&serv_addr,serv_len);

	//设置同时监听最大个数:
	listen(lfd,36);
	printf("Waiting for connecting...\n");

	//创建epoll根结点:
	int epfd = epoll_create(1000);//epoll_creat中的参数现在意义不大;

	//初始化epoll树:
	struct epoll_event ev;//创建一个事件:
	ev.events = EPOLLIN;
	ev.data.fd = lfd;
	epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);//将事件挂在树上,相当于初始化epoll树;

	struct epoll_event all[2000];//用数组储存这些事件,方便挂树,查询;

	while(1){
		  //使用epoll通知内核fd 文件IO检测;
		  int ret = epoll_wait(epfd,all,sizeof(all)/sizeof(all[0]),-1);//将检测到的epfd放到事件数组all中;
		  //返回值是数组中准备就绪的事件数;
		  
		  //遍历all数组中的前ret个元素:
		  for(int i = 0;i<ret;++i){
			  int fd = all[i].data.fd;
			  //提取出数组元素的fd,判断是否有连接:
			  if(fd == lfd){//这个if判断是判断用于监听的lfd是否加入到了ret中,如果加入了,就说明有新的连接;
				  int cfd = accept(lfd,(struct sockaddr*)&cli_addr,&cli_len);
				  if(cfd<0){
						perror("accept error");
						exit(1);
				  }
				//将新得到的cfd挂到树上:
				struct epoll_event temp;
				temp.events = EPOLLIN;
				temp.data.fd = cfd;
				epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&temp);

				//打印客户端信息:
				char ip[64];
				printf("New Client IP:%s ,\t Port:%d\n",inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,ip,sizeof(ip))  ,ntohs(cli_addr.sin_port));
			  }
			  else{
				    //处理已经连接的客户端发送过来的数据:
					if(!all[i].events & EPOLLIN){
						  continue ;
					}
					//读数据:
					char buf[1024];
					int len = recv(fd,buf,sizeof(buf),0);
					if(len<0){
						  perror("recv fail");
						  exit(1);
					}
					else if(len==0){
						  printf(" client disconnecting...\n ");
						  close(fd);
						  //fd从epoll树中取下来:
						  epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
					}
					else{
						  printf( "recv success:\n");
						  write(STDOUT_FILENO,buf,len);
					}
			  }
		  }
	}
	close(lfd);
	return 0;
}
发布了158 篇原创文章 · 获赞 37 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/XUCHEN1230/article/details/87259056