关于epoll服务器反馈的简单实现


#include<stdio.h>
#include<sys/epoll.h>
#include<signal.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<string.h>
#include<sys/types.h>
#include<fcntl.h>
#define MY_PORT 8848
#define MY_SIZE 100

int setnonblocking(int sockfd)
{
	if(fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)  
	{  
        	return -1;  
    	}
	return 0;  
}
int main(int argc,char *argv[])
{
	int server_pid,client_pid,fd,ndfs;
	int len,count;
	fd_set insert,tmp_insert;
	struct epoll_event ev;
	struct epoll_event events[20];

//	生成服务器描述符,SOSCK_STREAM表示面向链接稳定传送,即为tcp协议;
//	AF_INET表示ipv4,协议
	server_pid = socket(AF_INET,SOCK_STREAM,0);
	if(-1 == server_pid)
	{
		perror("socket error\n");
		exit(-1);
	}

//	定义网络结构体相关参数
	struct sockaddr_in my_addr;
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(MY_PORT);
	my_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
	len = sizeof(struct sockaddr);
	printf("socket....\n");
//	bind绑定
	if(-1 == bind(server_pid,(struct sockaddr*)&my_addr,len))
	{
		perror("bind error\n");
		exit(-2);
	}
	printf("binding...\n");
//	listen监听,第二个参数为限制listen后还未来得及accept的链接数
	if(-1 == listen(server_pid,5))
	{
		perror("listen error\n");
		exit(-3);
	}
	printf("listening.....");
	//fflush(stdout);
	struct sockaddr_in your_addr = {0};
//	创建epoll
	int epoll_fd = epoll_create(256);
	ev.data.fd=server_pid;
	ev.events=EPOLLIN|EPOLLET;
	int size = sizeof(struct sockaddr_in);
//	epoll事件注册
	char buf[MY_SIZE];
	epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_pid,&ev);//表示把server加入epoll的监听事件
	for(;;)
	{
		bzero(buf,MY_SIZE);
		ndfs = epoll_wait(epoll_fd,events,20,500);//20表示events变量有多大
		for(fd = 0;fd<ndfs;++fd)
		{
			if(events[fd].data.fd == server_pid)
			{
				client_pid = accept(server_pid,(struct sockaddr*)&your_addr,&size);
				if(-1 == client_pid)
				{
					perror("accept\n");
					exit(-4);
				}
			setnonblocking(client_pid);
			ev.events = EPOLLIN | EPOLLET;
			ev.data.fd=client_pid;

			//把客户端加入epoll监听
			epoll_ctl(epoll_fd,EPOLL_CTL_ADD,client_pid,&ev);
			printf("accept sucess!\n");

			}else if(events[fd].events&EPOLLIN) //EPOLLIN表示检测到输入,对应有EPOLLOUT为检测到输出 
			{
				//收到数据填入buffer
				if((count = recv(client_pid,buf,sizeof(buf),0)) <= 0)
        				{
            					close(fd);
					
						printf("Client %d has left\n",fd);
        				}
					else
					{
					//把buffer反馈给send
						printf("%d\n",count);
        					printf("recv:%s\n",buf);
        					if(-1 == send(client_pid,buf,sizeof(buf),0))
        					{
            						perror("send");
            						exit(-3);
        					}
					}
			}
		}
	}
close(server_pid);
return 0;
}

一。下面简单说说epoll几个函数的作用,它们分别为epoll_create,epoll_ctl,epoll_wait

1.int epoll_create(int size)

这个函数即为创建epoll的文件描述符,它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。

2.int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 

这个函数用来把文件描述符加入修改删除epoll,第一个参数epfd表示epoll_create返回的文件描述符;
第二个参数op表示要注册的事件:EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除;
第三个参数fd表示添加的进入epoll监听的文件描述符;
第四个参数event表示指向epoll_event的指针;
此函数调用成功返回0,不成功返回-1;

3.int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)

该函数用于轮询I/O事件的发生; 
参数: 
epfd:由epoll_create 生成的epoll专用的文件描述符; 
epoll_event:用于回传代处理事件的数组; 
maxevents:每次能处理的事件数; 
timeout:等待I/O事件发生的超时值(单位毫秒);
-1相当于阻塞,0相当于非阻塞。一般用-1即可 
返回发生事件数。 

二。事件结构体

typedef union epoll_data {   
void *ptr;   
int fd;   
__uint32_t u32;   
__uint64_t u64;   
} epoll_data_t;   
  
struct epoll_event {   
__uint32_t events; /* Epoll events */   
epoll_data_t data; /* User data variable */   
};  

常用的事件类型: 
EPOLLIN :表示对应的文件描述符可以读; 
EPOLLOUT:表示对应的文件描述符可以写; 
EPOLLPRI:表示对应的文件描述符有紧急的数据可读 
EPOLLERR:表示对应的文件描述符发生错误; 
EPOLLHUP:表示对应的文件描述符被挂断; 
EPOLLET:表示对应的文件描述符有事件发生; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值