统一事件源epoll代码示例
可以将信号注册进pipe管道的写端,通过对读端的监听,来实现统一事件源。
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h> #define MAX_EVENT_NUMBER 1024
static int pipefd[]; int setnonblocking(int fd) {
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK;
fcntl(fd, F_SETFL, new_option);
return old_option;
} void addfd(int epollfd, int fd) {
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
setnonblocking(fd);
} void sig_handler(int sig) {
int save_errno = errno;
int msg = sig;
send(pipefd[], (char*)&msg, , );
errno = save_errno;
} void addsig(int sig) {
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = sig_handler;
sa.sa_flags != SA_RESTART;
sigfillset(&sa.sa_mask);
assert(sigaction(sig, &sa, NULL) != -);
} int main(int argc, char *argv[]) {
if (argc <= ) {
printf("usage: %s ip port\n", basename(argv[]));
return ;
}
const char *ip = argv[];
int port = atoi(argv[]); int ret = ;
sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port); int listenfd = socket(PF_INET, SOCK_STREAM, );
assert(listenfd >= ); ret = bind(listenfd, (sockaddr*)&address, sizeof(address));
if (ret == -) {
printf("errno is %d\n", errno);
return ;
}
ret = listen(listenfd, );
assert(ret != -); epoll_event events[MAX_EVENT_NUMBER];
int epollfd = epoll_create();
assert(epollfd != -);
addfd(epollfd, listenfd); ret = socketpair(PF_UNIX, SOCK_STREAM, , pipefd);
assert(ret != -);
setnonblocking(pipefd[]);
addfd(epollfd, pipefd[]); addsig(SIGHUP);
addsig(SIGCHLD);
addsig(SIGTERM);
addsig(SIGINT);
bool stop_server = false; while (!stop_server) {
int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -);
if ((number < ) && (errno != EINTR)) {
printf("epoll failure\n");
break;
} for (int i=; i<number; i++) {
int sockfd = events[i].data.fd;
if (sockfd == listenfd) {
printf("New connection is coming.\n");
sockaddr_in client_address;
socklen_t client_addrlen = sizeof(client_address);
int connfd = accept(listenfd, (sockaddr*)&client_address,
&client_addrlen);
printf("New connection established.\n");
addfd(epollfd, connfd);
}
else if ((sockfd == pipefd[]) && (events[i].events & EPOLLIN)) {
int sig;
char signals[];
ret = recv(pipefd[], signals, sizeof(signals), );
if (ret == -) {
continue;
}
else if (ret == ) {
continue;
}
else {
for (int i=; i<ret; ++i) {
switch(signals[i]) {
case SIGCHLD:
{
printf("SIGCHLD CONTINUE\n");
continue;
}
case SIGHUP:
{
printf("SIGHUP CONTINUE\n");
continue;
}
case SIGTERM:
{
printf("SIGTERM END PROGRAM\n");
stop_server = true;
break;
}
case SIGINT:
{
printf("SIGINT END PROGRAM\n");
stop_server = true;
break;
}
}
}
}
}
else {
// handle connected fd, ignore
}
}
} printf("close fds\n");
close(listenfd);
close(pipefd[]);
close(pipefd[]);
return ; }
Makefile的文件内容:
uniserver : uniserver.cpp
g++ -o uniserver uniserver.cpp -lpthread
编译出服务器程序之后,运行服务器:
$ ./uniserver 127.0.0.1
New connection is coming.
New connection established.
SIGTERM END PROGRAM
close fds
$ ./uniserver 127.0.0.1
^CSIGINT END PROGRAM
close fds
运行客户端:
$ telnet 127.0.0.1
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
a
^C^]
telnet> quit
Connection closed.
$ ps ux | grep uniserver
work 0.0 0.0 pts/ S+ : : ./uniserver 127.0.0.1
work 0.0 0.0 pts/ S+ : : grep uniserver
$ kill
可以看出,客户端的连接请求得到服务器端的响应;发出的内容"a"在服务器端没有处理和展现。
使用向服务器发信号,得到处理;服务器端直接Ctrl+C也得到了处理。
同时可以看出,信号是int类型,但是传输的时候,采用的是char*,并且只传输了一个字节就可以了;在接收端进行switch的时候,也只针对char数据的一个元素进行比对就可以了。
统一事件源epoll代码示例的更多相关文章
- epoll代码示例
#include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types. ...
- 【NumberValidators】工商营业执照号码和统一社会信用代码验证
从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...
- Ice简介+Qt代码示例
1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,它封装并 ...
- MapReduce框架结构及代码示例
一个完整的 mapreduce 程序在分布式运行时有三类实例进程: 1.MRAppMaster:负责整个程序的过程调度及状态协调 2.MapTask:负责 map 阶段的整个数据处理流程 3.Redu ...
- 高级渲染技巧和代码示例 GPU Pro 7
下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...
- Java8-Function使用及Groovy闭包的代码示例
导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...
- [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例
懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
- SELECT控件操作的JS代码示例
SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...
- 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好
HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...
随机推荐
- [Unity3D]unity3d5.0简单的调用摄像头
Unity3D中新建一个工程,加一个Plane,新建一个C# 脚本,将这个脚本添加到Plane上,调用摄像头.(如果显示的图片居然是翻转的,Plane的Rotation 值就可以了) 以下是脚本内容: ...
- 凯撒加密解密(java字母移位)
1.设计思想:加密就是将字符数据转化为ASC码表中的数字,a—w之间通过加3之后再转化为字符型输出,x—z之间通过转化为ASC码表中的数字后减去23再转化为字符型输出.解密就是将字符数据转化为ASC码 ...
- JAVA类访问URL
URI uri = new URI("https://www.baidu.com/"); Desktop desktop = null; if (Des ...
- 周赛-Toy Cars 分类: 比赛 2015-08-08 15:41 5人阅读 评论(0) 收藏
Toy Cars time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...
- Git合并开发代码分支到测试代码分支
——转载请注明出自天外归云的博客园 用TortoiseGit下载代码到本地 首先需要在本机安装好TortoiseGit.然后在随便哪个路径下比如D盘,右键“Git Clone”: 然后URL处选择项目 ...
- A fatal error has been detected by the Java Runtime Environment(jdk 1.6的一个BUG)
几天做项目,生成一堆注解的实体,当实体数超过86个时,jvm报错: # # A fatal error has been detected by the Java Runtime Environmen ...
- UML实践详细经典教程----用例图、顺序图、状态图、类图、包图、协作图
面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是Unified Modeling Language™),这篇课程的目的是展示出UML ...
- Xcode_5
Xcode_5 Objective-C进行IOS7编程 我个人的经验是,如果之前有过编程基础(无论是C.C++还是Java),那么<Objective-C基础教程>(图灵程序设计丛书 ...
- HDU 1004 Let the Balloon Rise map
Let the Balloon Rise Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- Python3基础 count 返回指定元素在列表中的个数
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...