epoll实现服务器

使用epoll实现简单的服务器,熟悉下epoll接口的使用,不作详细的原理分析。

在这里插入代码片
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_create1(int flags);

int epoll_ctl(int epds, int op, int fd, struct epoll_event *event);

EPOLL_CTL_ADD
Register the target file descriptor fd on the epoll instance referred to by the file descriptor epfd and as‐
sociate the event event with the internal file linked to fd.
EPOLL_CTL_MOD
Change the event event associated with the target file descriptor fd.
EPOLL_CTL_DEL
Remove (deregister) the target file descriptor fd from the epoll instance referred to by epfd.  The event is ignored and can be NULL (but see BUGS below).

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 */
};

int epoll_wait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout,
                      const sigset_t *sigmask);//
收集在epoll监控的事件中已经发送的事件。参数events是分配好的epoll_event结构体数组,epoll将会把发生的事件赋值到events数组中(events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存)。maxevents告之内核这个events有多大,这个 maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将是永久阻塞)。如果函数调用成功,返回对应I/O上已准备好的文件描述符数目,如返回0表示已超时

在这里插入代码片
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> 
#include <time.h>
#include <string.h>
#include <poll.h>
#include <sys/epoll.h>
#include <limits.h>
#include <errno.h>
 
#define MAXLINE 1024
#define FILE_MAX 128
#define INFTIM -1
#define PORT 9000
 
char buf[MAXLINE];

#if 1
void to_up(char *p) {
	int len = strlen(p);
	int i = 0;
	while(i < len) {
		if (p[i] <= 'z' && p[i] >= 'a') {
			p[i] -= 32; 
		}
		i++;
    }
	p[i] = '\0';
}
#endif
int main(int argc, char **argv)
{
	int i, listenfd, connfd, sockfd, epollfd, nfds;
	int nready;
	ssize_t n;
	
	socklen_t clilen;
	struct pollfd client[FILE_MAX];
	struct sockaddr_in cliaddr, serveraddr;
	struct epoll_event ev, events[20];
 
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&serveraddr,sizeof(serveraddr));
 
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serveraddr.sin_port = htons(PORT);
 
	if (bind(listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1) {
		perror("bind error:\n");
		exit(-1);
	}
	if (listen(listenfd,128) == -1) {
		printf("listen error\n");
		exit(-1);
	}
	epollfd = epoll_create1(0);
	ev.data.fd = listenfd;
	ev.events = EPOLLIN|EPOLLET;
	epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);
 
	for(; ;) {
		nfds = epoll_wait(epollfd, events, 20, -1);
		for(i = 0;i < nfds; ++i) {
			if(events[i].data.fd == listenfd) {
				clilen = sizeof(cliaddr);
				connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
				if(connfd < 0) {
					perror("accept error");
					continue;
				}
 
				printf("connection from %s, port is %d\n", inet_ntop(AF_INET,&cliaddr.sin_addr,buf,sizeof(buf)),ntohs(cliaddr.sin_port));
				ev.events = EPOLLIN|EPOLLET;
				ev.data.fd = connfd;
				if(epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev) < 0) {
					fprintf(stderr, "epoll set insertion error: fd = %d\n", connfd);
					return -1;
				}
			} else {
				int n;
				int sockfd = events[i].data.fd;
 
				if(events[i].events & EPOLLIN) {	
					memset(buf, 0, MAXLINE);
					if(sockfd < 0)
						continue;
 
					if((n = read(sockfd, buf, MAXLINE)) < 0) {
						close(sockfd);
						sockfd = -1;
						perror("read error");
						return ;
					}
					else if(n == 0) {
						printf("terminated from port %d\n", ntohs(cliaddr.sin_port));
						close(sockfd);
						sockfd = -1;
					} else {
						printf("read %d characters\n", n - 1);
						ev.data.fd = sockfd;
						ev.events = EPOLLOUT|EPOLLET;
 
						epoll_ctl(epollfd, EPOLL_CTL_MOD, sockfd, &ev);
					}
				}
				if(events[i].events & EPOLLOUT) {
					if(sockfd < 0)
						continue;
 					to_up(buf);
					if((n = write(sockfd, buf, strlen(buf))) < 0) {
						perror("write error");
						return ;
					} else {
						printf("write %d characters\n", (n - 1) > 0?(n-1):0);
						ev.data.fd = sockfd;
						ev.events = EPOLLIN|EPOLLET;
						bzero(buf, n);
						epoll_ctl(epollfd, EPOLL_CTL_MOD, sockfd, &ev);
					}
				}
			}
		}
	}
 
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值