可以将信号注册进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代码示例的更多相关文章

  1. epoll代码示例

    #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types. ...

  2. 【NumberValidators】工商营业执照号码和统一社会信用代码验证

    从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...

  3. Ice简介+Qt代码示例

    1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,它封装并 ...

  4. MapReduce框架结构及代码示例

    一个完整的 mapreduce 程序在分布式运行时有三类实例进程: 1.MRAppMaster:负责整个程序的过程调度及状态协调 2.MapTask:负责 map 阶段的整个数据处理流程 3.Redu ...

  5. 高级渲染技巧和代码示例 GPU Pro 7

    下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...

  6. Java8-Function使用及Groovy闭包的代码示例

    导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...

  7. [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例

    懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...

  8. SELECT控件操作的JS代码示例

    SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...

  9. 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好

    HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...

随机推荐

  1. 层叠样式表(CSS)

    层叠样式表(CSS) CSS(Cascading Style Sheet)中文译为层叠样式表.是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言.CSS的引入就是为了使得HTML语言能够 ...

  2. 每日一九度之 题目1076:N的阶乘

    时间限制:3 秒 内存限制:128 兆 特殊判题:否 提交:7601 解决:2749 题目描述: 输入一个正整数N,输出N的阶乘. 输入: 正整数N(0<=N<=1000) 输出: 输入可 ...

  3. 如何将vs2012项目的网站布置到iis上,实现内网访问

    1首先获得你本机的ip地址 可以通过命令行输入 ipconfig/all 2配置电脑的iis(前提是你已经安装了) 右击我的电脑选择管理 右键网站添加网页 会出来上面的对话框 选择直接的项目web路径 ...

  4. js去除日期字符串时分秒

    var date = "2015-11-11 00:00:00"; var newDate=/\d{4}-\d{1,2}-\d{1,2}/g.exec(date) newDate= ...

  5. 跨站点脚本编制实例(AppScan扫描结果)

    最近工作要求解决下web的项目的漏洞问题,扫描漏洞是用的AppScan工具,其中有很多是关于跨站点脚本编制问题的.下面就把这块东西分享出来. 原创文章,转载请注明 ------------------ ...

  6. Jenkins构建Git manager服务器的源码

    1,下载scm manager 源码库管理,下载后解压即可: 2,运行bin目录下的scm-server.bat文件,启动服务: 3,建议将scm-server放在git客户端的安装目录下,方便管理 ...

  7. easyui表单插件-包括日期时控件-列表

    ← jQuery EasyUI 表单插件 – Numberspinner 数值微调器 jQuery EasyUI 表单插件 - Timespinner 时间微调器  jQuery EasyUI 插件 ...

  8. 改变了一下blog的主题,很开心

    调整了一下博客的样式,之前一直想改变下,一直不会这次终于摸索出来一点,不过是最简单的,就是在管理里面的设置,可以定制css代码,修改修改,页面就跟着你的想法走了,有时间好好修改下,暂时这个样子,简单大 ...

  9. Struts2的处理结果(二)——处理结果的类型

    Struts2的处理结果(二) --处理结果的类型 1.Struts2內建的支持的结果类型: 在<result>元素中的type属性,确定了结果类型. chain:Action链式处理的结 ...

  10. c#调用cmd的ping命令

    private static string CmdPing(string strIp) { Process p = new Process(); p.StartInfo.FileName = &quo ...