Linux IO多路复用之epoll网络编程及源码(转)
原文:
前言
本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:
客户端从标准输入读入一行,发送到服务端
服务端从网络读取一行,然后输出到客户端
客户端收到服务端的响应,输出这一行到标准输出
服务端代码
代码如下:
#include <unistd.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h> /* inet(3) functions */
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h> /* nonblocking */
#include <sys/resource.h> /*setrlimit */ #include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h> #define MAXEPOLLSIZE 10000
#define MAXLINE 10240
int handle(int connfd);
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, )|O_NONBLOCK) == -) {
return -;
}
return ;
} int main(int argc, char **argv)
{
int servPort = ;
int listenq = ; int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = ;
struct sockaddr_in servaddr, cliaddr;
socklen_t socklen = sizeof(struct sockaddr_in);
struct epoll_event ev;
struct epoll_event events[MAXEPOLLSIZE];
struct rlimit rt;
char buf[MAXLINE]; /* 设置每个进程允许打开的最大文件数 */
rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
if (setrlimit(RLIMIT_NOFILE, &rt) == -)
{
perror("setrlimit error");
return -;
} bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
servaddr.sin_port = htons (servPort); listenfd = socket(AF_INET, SOCK_STREAM, );
if (listenfd == -) {
perror("can't create socket file");
return -;
} int opt = ;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (setnonblocking(listenfd) < ) {
perror("setnonblock error");
} if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -)
{
perror("bind error");
return -;
}
if (listen(listenfd, listenq) == -)
{
perror("listen error");
return -;
}
/* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
kdpfd = epoll_create(MAXEPOLLSIZE);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listenfd;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < )
{
fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
return -;
}
curfds = ; printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq); for (;;) {
/* 等待有事件发生 */
nfds = epoll_wait(kdpfd, events, curfds, -);
if (nfds == -)
{
perror("epoll_wait");
continue;
}
/* 处理所有事件 */
for (n = ; n < nfds; ++n)
{
if (events[n].data.fd == listenfd)
{
connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
if (connfd < )
{
perror("accept error");
continue;
} sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
printf("%d:%s", ++acceptCount, buf); if (curfds >= MAXEPOLLSIZE) {
fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
close(connfd);
continue;
}
if (setnonblocking(connfd) < ) {
perror("setnonblocking error");
}
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = connfd;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < )
{
fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
return -;
}
curfds++;
continue;
}
// 处理客户端请求
if (handle(events[n].data.fd) < ) {
epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
curfds--; }
}
}
close(listenfd);
return ;
}
int handle(int connfd) {
int nread;
char buf[MAXLINE];
nread = read(connfd, buf, MAXLINE);//读取客户端socket流 if (nread == ) {
printf("client close the connection\n");
close(connfd);
return -;
}
if (nread < ) {
perror("read error");
close(connfd);
return -;
}
write(connfd, buf, nread);//响应客户端
return ;
}
编译和启动服务端
gcc epollserver.c -o epollserver
./epollserver
客户端代码
至于客户端可以参考本文的Linux/Unix服务端和客户端Socket编程入门实例的echoclient例子下载编译
Linux IO多路复用之epoll网络编程及源码(转)的更多相关文章
- Linux IO多路复用之epoll网络编程(含源码)
前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...
- Linux IO多路复用之epoll网络编程
前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...
- 《 UNIX网络编程》源码的使用
学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:h ...
- Unix 网络编程卷一源码编译踩坑记录 ubtutu 19.10
在阅读unpv1时运行源代码的环境配置,这里简单记录一下 源代码里的README 写得挺详细的,但是在Linux 系统的下还没没办法直接编译通过的, 这里我使用的是ubuntu 19.10(在腾讯云1 ...
- 【知乎网】Linux IO 多路复用 是什么意思?
提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...
- python 网络编程 IO多路复用之epoll
python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解 此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...
- Java网络编程和NIO详解3:IO模型与Java网络编程模型
Java网络编程和NIO详解3:IO模型与Java网络编程模型 基本概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32 ...
- Linux IO多路复用 poll
Linux IO多路复用 poll 之前曾经提到过 select poll 跟select类似,poll改进了select的一个确定,就是poll没有监听上限 不过poll还是需要遍历以及频繁的把数组 ...
- Linux IO多路复用 select
Linux IO多路复用 select 之前曾经写过简单的服务器,服务器是用多线程阻塞,客户端每一帧是用非阻塞实现的 后来发现select可以用来多路IO复用,就是说可以把服务器这么多线程放在一个线程 ...
随机推荐
- BugHD 与你的应用一起成长
BugHD 新增功能 1.新增安装量.启动量的统计功能 BugHD SDK 1.3.0新增安装量.启动量的统计功能,在崩溃分析页面右上角可看到安装量和启动量. BugHD 体验优化 1.Android ...
- Java中有几种线程池?
缓存,修正,计划,单一 newCachedThreadPool newFixedThreadPool newScheduleThreadPool newSingleThreadExecutor
- JSP中的动态包含和静态包含的区别
本文转载自http://blog.csdn.net/xuxu198899223/article/details/8501044 1. 语法格式 (1)静态包含:<%@ include file= ...
- C# mvc 500 内部服务器访问异常
20161018 项目发布到IIS上后,无法访问,由于页面默认跳转到异常处理去了,所以详细信息一直查看不了. 在找寻无果,异常信息日志记录无效的情况下,只好一点点来测试了 在异常处理前,就已经试过,a ...
- Linux设备驱动剖析之IIC(一)
写在前面 由于IIC总线只需要两根线就可以完成读写操作,而且通信协议简单,一条总线上可以挂载多个设备,因此被广泛使用.但是IIC总线有一个缺点,就是传输速率比较低.本文基于Linux-2.6.36版本 ...
- 【python】解决No module named _sqlite3的问题
环境版本说明: centos 7 python3.6.4 django 2.0 在创建django项目时候.报错以下信息 详细错误信息如下: 原因: 未安装sqlite 模块 解决: 1 安装 sql ...
- 【分享】IT产业中的三大定理(三) —— 反摩尔定理 (Reverse Moore's Law)
Google(谷歌)的 CEO 埃里克·施密特在一次采访中指出,如果你反过来看摩尔定理,一个 IT 公司如果今天和十八个月前卖掉同样多的.同样的产品,它的营业额就要降一半.IT 界把它称为反摩尔定理. ...
- 百度编辑器(UEditor)自定义工具栏
百度编辑器(UEditor)自定义工具栏的自定义 百度编辑器默认功能比较齐全,但是不一定是我们所需要的,有的功能可以去掉,用自己想要的就可以了,可以参考百度官方文档! 百度编辑器默认配置展示界面 如何 ...
- java (10) 集合类
1.集合概述 集合按照存储结构可以分为两类,即单列集合 Collection 和双列集合 Map. * Collection 用于存储一系列符合某种规则的元素,它有两个重要的自接口,分别是List和S ...
- 23种设计模式之外观模式(Facade)
外观模式是对象的结构模式,要求外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 优点: 1 ...