原文:

前言

本章节是用基本的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网络编程及源码(转)的更多相关文章

  1. Linux IO多路复用之epoll网络编程(含源码)

    前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...

  2. Linux IO多路复用之epoll网络编程

    前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...

  3. 《 UNIX网络编程》源码的使用

    学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:h ...

  4. Unix 网络编程卷一源码编译踩坑记录 ubtutu 19.10

    在阅读unpv1时运行源代码的环境配置,这里简单记录一下 源代码里的README 写得挺详细的,但是在Linux 系统的下还没没办法直接编译通过的, 这里我使用的是ubuntu 19.10(在腾讯云1 ...

  5. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  6. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

  7. Java网络编程和NIO详解3:IO模型与Java网络编程模型

    Java网络编程和NIO详解3:IO模型与Java网络编程模型 基本概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32 ...

  8. Linux IO多路复用 poll

    Linux IO多路复用 poll 之前曾经提到过 select poll 跟select类似,poll改进了select的一个确定,就是poll没有监听上限 不过poll还是需要遍历以及频繁的把数组 ...

  9. Linux IO多路复用 select

    Linux IO多路复用 select 之前曾经写过简单的服务器,服务器是用多线程阻塞,客户端每一帧是用非阻塞实现的 后来发现select可以用来多路IO复用,就是说可以把服务器这么多线程放在一个线程 ...

随机推荐

  1. BugHD 与你的应用一起成长

    BugHD 新增功能 1.新增安装量.启动量的统计功能 BugHD SDK 1.3.0新增安装量.启动量的统计功能,在崩溃分析页面右上角可看到安装量和启动量. BugHD 体验优化 1.Android ...

  2. Java中有几种线程池?

    缓存,修正,计划,单一 newCachedThreadPool newFixedThreadPool newScheduleThreadPool newSingleThreadExecutor

  3. JSP中的动态包含和静态包含的区别

    本文转载自http://blog.csdn.net/xuxu198899223/article/details/8501044 1. 语法格式 (1)静态包含:<%@ include file= ...

  4. C# mvc 500 内部服务器访问异常

    20161018 项目发布到IIS上后,无法访问,由于页面默认跳转到异常处理去了,所以详细信息一直查看不了. 在找寻无果,异常信息日志记录无效的情况下,只好一点点来测试了 在异常处理前,就已经试过,a ...

  5. Linux设备驱动剖析之IIC(一)

    写在前面 由于IIC总线只需要两根线就可以完成读写操作,而且通信协议简单,一条总线上可以挂载多个设备,因此被广泛使用.但是IIC总线有一个缺点,就是传输速率比较低.本文基于Linux-2.6.36版本 ...

  6. 【python】解决No module named _sqlite3的问题

    环境版本说明: centos 7 python3.6.4 django 2.0 在创建django项目时候.报错以下信息 详细错误信息如下: 原因: 未安装sqlite 模块 解决: 1 安装 sql ...

  7. 【分享】IT产业中的三大定理(三) —— 反摩尔定理 (Reverse Moore's Law)

    Google(谷歌)的 CEO 埃里克·施密特在一次采访中指出,如果你反过来看摩尔定理,一个 IT 公司如果今天和十八个月前卖掉同样多的.同样的产品,它的营业额就要降一半.IT 界把它称为反摩尔定理. ...

  8. 百度编辑器(UEditor)自定义工具栏

    百度编辑器(UEditor)自定义工具栏的自定义 百度编辑器默认功能比较齐全,但是不一定是我们所需要的,有的功能可以去掉,用自己想要的就可以了,可以参考百度官方文档! 百度编辑器默认配置展示界面 如何 ...

  9. java (10) 集合类

    1.集合概述 集合按照存储结构可以分为两类,即单列集合 Collection 和双列集合 Map. * Collection 用于存储一系列符合某种规则的元素,它有两个重要的自接口,分别是List和S ...

  10. 23种设计模式之外观模式(Facade)

    外观模式是对象的结构模式,要求外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 优点: 1 ...