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复用,就是说可以把服务器这么多线程放在一个线程 ...
随机推荐
- beef 安装使用
http://www.freebuf.com/articles/web/5511.html
- zabbix的启动和关闭脚本
1. zabbix客户端的系统服务脚本 1.1 拷贝启动脚本 zabbix的源码提供了系统服务脚本,在/usr/local/src/zabbix-3.2.6/misc/init.d目录下,我的系统是C ...
- jq判断滚动条向上还是向下
$(document).ready(function(){ ,t=; $(window).scroll(function(e){ p = $(this).scrollTop(); if(t<=p ...
- Java网络编程之查找Internet地址
一.概述 连接到Internet上计算机都有一个称为Internet地址或IP地址的唯一的数来标识.由于IP很难记住,人们设计了域名系统(DNS),DNS可以将人们可以记忆的主机名与计算机可以记忆的I ...
- RabbitMQ与java、Spring结合实例详细讲解
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文介绍了rabbitMq,提供了如何在Ubuntu下安装RabbitMQ 服务的方法. ...
- Android自定义字体
1.在assets中创建文件夹fonts,放入字体文件.ttf 2.使用实例: TextView tv= (TextView)findViewById(R.id.tv); Typeface tf = ...
- java基础---->使用Itext生成数据库文档
这里简单的介绍一下使用Itext生成数据库表的文档.于是我们领教了世界是何等凶顽,同时又得知世界也可以变得温存和美好. 生成数据库的文档 一.maven项目需要引入的jar依赖 <depende ...
- 【CSS系列】height:100%设置div的高度
一.div设置百分百高度实现描述 在html布局中body内第一个div盒子对象设置100%高度height样式,是无法成功显示100%高度的.这个是因为body高度默认值为自适应的,所以及时设置bo ...
- Ubuntu 14.04 LTS 火狐浏览器中,鼠标选择文字被删除的解决办法
这篇文章主要介绍了Ubuntu 火狐浏览器中,鼠标选择文字被删除的解决办法,需要的朋友可以参考下在终端中输入命令: ibus-setup将 “在应用程序窗口中启用内嵌编辑模式“ 选项取消
- 安卓APP动态调试-IDA实用攻略
0x00 前言 随着智能手机的普及,移动APP已经贯穿到人们生活的各个领域.越来越多的人甚至已经对这些APP应用产生了依赖,包括手机QQ.游戏.导航地图.微博.微信.手机支付等等,尤其2015年春节期 ...