linux网络编程----->高并发--->epoll多路I/O转接服务器

做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.

常见的linux并发服务器模型;

    • 多进程并发服务器
    • 多线程并发服务器
    • select多路I/O转接服务器
    • poll多路I/O转接服务器
    • epool多路I/O转接服务器.

本次主要讨论poll多路I/转接并发服务器模型:

前几章介绍完了多进程并发服务器,  多线程并发服务器selete多路I/O转接服务器,  poll多路I/O转接服务器, 本章开始介绍epoll(linux特有)多路I/O转接模型.

由于多进程和多线程模型在实现中相对简单, 但由于其开销和CPU高度中比较大, 所以一般不用多线程和多进程来实现服务模型. select由于其跨平台, 但其最高上限默认为1024, 修改突破1024的话需要重新编译linux内核, poll虽然解决了select1024的限制, 但由于poll本质实现上也是轮循机制, 所以对于客户端的增加也会使效率降低.  本章来详细介绍epoll多路I/O转发服务器模型.

epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。

目前epell是linux大规模并发网络程序中的热门首选模型。

epoll除了提供select/poll那种IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

主要用到的API:

int epoll_create(int size);

简介: 创建epoll句柄

参数: 监听数量

int epoll_ctl(int epfd, int op, int fd, struct epoll_event* evvent);

简单: 控制某个epoll监听的文件描述符上的事件, 注册, 修改, 删除

epfd: 为epoll_create的句柄

op:   动作, 用3个宏来表示

EPOLL_CTL_ADD  注册新的fd到epfd

EPOLL_CTL_MOD  修改已经注册的fd的监听事件

EPOLL_CTL_DEL  从epfd删除一个fd

event: 告诉内核需要监听的事件

struct epoll_event{

__uint32_t events;        /*Epoll events*/

epoll_data_t data;        /"use data variable"/

}

typedef union epoll_data{

void* ptr;

int fd;

uint32_t u32;

uint64_t u64;

}epoll_data_t;

EPOLLIN 监听读事件,  EPOLLOUT 监听写事件   EPOLLERR 监听异常事件

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

函数说明: 等待所监控文件描述符上有事件的产生.

epfd: 为epoll_create的句柄

events: 用来存内核得到事件的集合

maxevents:  告之内核这个events有多大, 这个maxevents的值不能大于创建epoll_create()的size

timeout: 等待时间

-1: 阻塞等待

0: 立即返回, 非阻塞

>0: 指定毫秒

返回值: 成功返回有多少文件描述符就绪, 时间到时返回0, 出错返回-1

代码如下:

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

#define SERV_PORT 9096	//服务端口
#define CLIENT_MAX 1024	//客户端最大连接

int main(int argc, char* argv[]){
	int listenfd, connfd, efd;
	struct sockaddr_in serv_addr, clie_addr;
	socklen_t clie_addr_len;
	char buf[BUFSIZ];
	int n, i, j, nready, opt;
	struct epoll_event op[CLIENT_MAX+1], ep;

	//创建监听套接字
	listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	//设置端口复用
	opt = 1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	//绑定地址族
	bzero(&serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERV_PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

	//设置连接同时最高上限
	listen(listenfd, SOMAXCONN);

	//创建epoll
	efd = epoll_create(CLIENT_MAX+1);

	//添加请求连接监听套接字
	ep.events = EPOLLIN;
	ep.data.fd = listenfd;
	epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &ep);

	for(;;){
		//监听事件
		nready = epoll_wait(efd, op, CLIENT_MAX + 1, -1);
		for(i = 0; i < nready; i++){
			if(!(op[i].events & EPOLLIN))
				continue;
			//当有连接请求
			if(op[i].data.fd == listenfd){
				clie_addr_len = sizeof(clie_addr);
				//获取连接
				connfd = accept(listenfd, (struct sockaddr*)&clie_addr, &clie_addr_len);
				printf("%s:%d connect successfully!\n", inet_ntoa(clie_addr.sin_addr), ntohs(clie_addr.sin_port));
				//监听读事件
				ep.events = EPOLLIN;
				ep.data.fd = connfd;
				//添加至监听
				epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &ep);
			}else{	//客房端消息
				bzero(buf, sizeof(buf));
				n = read(op[i].data.fd, buf, sizeof(buf));
				//客户端关闭连接
				if(0 == n){
				    //从监听中移除
				    epoll_ctl(efd, EPOLL_CTL_DEL, op[i].data.fd, NULL);
				    //关闭连接
				    close(op[i].data.fd);
				}else{

					//转为大写
					for(j = 0; j < n; j++){
						buf[j] = toupper(buf[j]);
					}
					//回写给客户端
					write(op[i].data.fd, buf, n);
				}
			}
		}
	}
	close(listenfd);
	close(efd);
	return 0;
}
时间: 2024-10-05 05:58:48

linux网络编程----->高并发--->epoll多路I/O转接服务器的相关文章

linux网络编程-----&gt;高并发---&gt;poll多路I/O转接服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论poll多路I/转接并发服务器模型: 前几章介绍完了多进程并发服务器,  多线程并发服务器, selete多路I/O转接服务器,  本章开始介绍poll(linux特有)多路

linux网络编程-----&gt;高并发---&gt;select多路I/O复用服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论select多路I/O转接服务器模型: 使用select多路I/O转接服务器模型要考虑到以下几点: 1. select能监听的文件描述符个数受限于FD_SETSIZE, 一般

linux网络编程-----&gt;高并发---&gt;多进程并发服务器

在做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论多线程并发服务器模型: 使用多进程并发服务器时要考虑以下几点: 父进程最大文件描述个数(父进程中需要close关闭accpet返回的新文件描述符) 系统内创建进程个数(与内

linux网络编程-----&gt;高并发---&gt;多线程并发服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论多线程并发服务器模型: 使用多线程模型开发服务时需要考虑以下问题 1.  调整进程内最大文件描述符上限. 2.  线程如有共享数据, 考虑线程同步. 3.  服务于客户端线程

Linux网络编程——多路复用之epoll

目录 Linux网络编程--多路复用之epoll 基础API 实例一.epoll实现在线聊天 实例二.epoll实现在客户端断开后服务端能一直运行,客户端可以多次重连 Linux网络编程--多路复用之epoll ? epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,

Linux网络编程——tcp并发服务器(poll实现)

想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/O复用之poll函数> 代码: #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include <sys/socket.h> #incl

Linux 网络编程八(epoll应用--大并发处理)

//头文件 pub.h #ifndef _vsucess #define _vsucess #ifdef __cplusplus extern "C" { #endif //服务器创建socket int server_socket(int port); //设置非阻塞 int setnonblock(int st); //接收客户端socket int server_accept(int st); //关闭socket int close_socket(int st); //接收消息

Linux网络编程——tcp并发服务器(多进程)

一.tcp并发服务器概述 一个好的服务器,一般都是并发服务器(同一时刻可以响应多个客户端的请求).并发服务器设计技术一般有:多进程服务器.多线程服务器.I/O复用服务器等. 二.多进程并发服务器 在 Linux 环境下多进程的应用很多,其中最主要的就是网络/客户服务器.多进程服务器是当客户有请求时,服务器用一个子进程来处理客户请求.父进程继续等待其它客户的请求.这种方法的优点是当客户有请求时,服务器能及时处理客户,特别是在客户服务器交互系统中.对于一个 TCP 服务器,客户与服务器的连接可能并不

linux网络编程-----实现并发访问网站------

一般在测试多并发服务器的时候需要使用多路进程访问,这时需要自己来编写测试的并发访问功能. 直接上代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> //回收子进程 void wait_child(int num){ while(0 < waitpid(0, NULL, WNOHANG)