epoll服务器

目前堪称完美epoll服务器:




#include 
#include 
#include 
#include 
#include 
#include 
#include 

static void Usage(const char *proc)
{
	printf("Usage:%s[local_ip][local_port]\n", proc);
}

typedef struct fd_buf{
	int fd;
	char buf[10240];
}fd_buf_t, *fd_buf_p;

static void *alloc_fd_buf(int fd)
{
	fd_buf_p tmp = (fd_buf_p)malloc(sizeof(fd_buf_t));
	if(!tmp)
	{
		perror("malloc");
		return NULL;
	}
	tmp->fd = fd;
	return tmp;
}

int startup(const char *_ip, int _port)
{
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock < 0)
	{
		perror("sock");
		exit(2);
	}
	int opt = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_port = htons(_port);
	local.sin_addr.s_addr =inet_addr(_ip);

	if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)
	{
		perror("bind");
		exit(3);
	}

	if(listen(sock, 10) < 0)
	{
		perror("listen");
		exit(4);
	}

	return sock;
}

int main(int argc, char* argv[])
{
	if(argc != 3)
	{
		Usage(argv[0]);
		return 1;
	}
	int listen_sock = startup(argv[1], atoi(argv[2]));

	int epollfd = epoll_create(256);
	if(epollfd < 0)
	{
		perror("epoll_create");
		close(listen_sock);
		return 5;
	}

	struct epoll_event ev;
	ev.events = EPOLLIN;
	ev.data.ptr = alloc_fd_buf(listen_sock);
	epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev);

	int nums = 0;
	struct epoll_event evs[64];
	int timeout = -1;
	while(1)
	{
		switch((nums = epoll_wait(epollfd, evs, 64, timeout)))
		{
			case -1:
				perror("epoll_wait");
				break;
			case 0:
				printf("timeout.....!\n");
				break;
			default:
				{
					int i = 0;
					for(; i < nums; i++)
					{
						fd_buf_p fp = (fd_buf_p)evs[i].data.ptr;
						if(fp->fd == listen_sock && (evs[i].events & EPOLLIN))
						{
							struct sockaddr_in client;
							socklen_t len = sizeof(client);
							int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len);
							if(new_sock < 0)
							{
								perror("accept");
								continue;
							}
							printf("get a new client!\n");
							ev.events = EPOLLIN;
							ev.data.ptr = alloc_fd_buf(new_sock);
							epoll_ctl(epollfd, EPOLL_CTL_ADD, new_sock, &ev);
						}
						else if(fp->fd != listen_sock)
						{
							if(evs[i].events & EPOLLIN)
							{
								ssize_t s = read(fp->fd, fp->buf, sizeof(fp->buf));
								if(s > 0)
								{
									fp->buf[s] = 0;
									printf("client say: %s\n", fp->buf);
									ev.events = EPOLLOUT;
									ev.data.ptr = fp;
									epoll_ctl(epollfd, EPOLL_CTL_MOD, fp->fd, &ev);
								}else if(s <= 0)
								{
									close(fp->fd);
									epoll_ctl(epollfd, EPOLL_CTL_DEL, fp->fd, NULL);
									free(fp);
								}else
								{}
							}else if(evs[i].events & EPOLLOUT)
							{
								const char *msg = "HTTP/1.0 200 OK\r\n\r\n

hello epoll!

"; write(fp->fd, msg, strlen(msg)); close(fp->fd); epoll_ctl(epollfd, EPOLL_CTL_DEL, fp->fd, NULL); free(fp); }else {} }else {} } } break; } } return 0; }
### 实现 Epoll 服务器 EpollLinux 下多路复用 I/O 接口的一种,用于高效处理大量并发连接。通过 `epoll_create` 函数可以创建一个新的 epoll 实例并返回一个文件描述符[^1]。 下面是一个简单的基于 C 语言的 Epoll 非阻塞 TCP 服务器示例: ```c #include <sys/epoll.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #define MAX_EVENTS 10 #define BUFFER_SIZE 1024 int main() { int listen_fd, conn_fd; struct sockaddr_in server_addr; // 创建监听套接字 if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(EXIT_FAILURE); } memset(&server_addr, '0', sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); listen(listen_fd, SOMAXCONN); // 设置为非阻塞模式 fcntl(listen_fd, F_SETFL, O_NONBLOCK); // 创建 epoll 实例 int epoll_fd = epoll_create(MAX_EVENTS); if (epoll_fd == -1){ perror("epoll_create error"); close(listen_fd); exit(EXIT_FAILURE); } struct epoll_event event; event.events = EPOLLIN | EPOLLET; // 边缘触发方式 event.data.fd = listen_fd; // 将监听套接字加入到 epoll 中 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event) == -1){ perror("epoll_ctl add listen fd error"); close(listen_fd); close(epoll_fd); exit(EXIT_FAILURE); } struct epoll_event events[MAX_EVENTS]; char buffer[BUFFER_SIZE]; while(true){ int n_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); for(int i=0;i<n_fds;++i){ if(events[i].data.fd==listen_fd){ socklen_t addr_len = sizeof(struct sockaddr_in); conn_fd = accept(listen_fd,(struct sockaddr*)&server_addr,&addr_len); set_nonblocking(conn_fd); //设置新连接为非阻塞 event.data.fd = conn_fd; event.events = EPOLLIN|EPOLLET; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &event); }else{ ssize_t bytes_read=read(events[i].data.fd,buffer,BUFFER_SIZE-1); if(bytes_read>0){ buffer[bytes_read]='\0'; printf("received data: %s\n",buffer); write(events[i].data.fd,"message received",strlen("message received")); }else{ close(events[i].data.fd); epoll_ctl(epell_fd, EPOLL_CTL_DEL,events[i].data.fd,NULL); } } } } return EXIT_SUCCESS; } ``` 此程序展示了如何利用 Epoll 来构建高效的事件驱动型网络服务端应用。它能够有效地管理多个客户端连接而不会因为过多的线程或进程造成资源浪费。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值