可以将信号注册进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. Android中的图片压缩

    1.android中计算图片占用堆内存的kB大小跟图片本身的kB大小无关,而是根据图片的尺寸来计算的. 比如一张 480*320大小的图片占用的堆内存大小为: 480*320*4/1024=600kB ...

  2. 修改tomcat的logo

    每页的<head> 里添加   <link rel="icon" href="favicon.gif" />   图片名称必须是favi ...

  3. java中@value的环境配置

    @value 在现阶段我想大家对注解都不陌生,@value的用法就是在后台获取配置文件的信息,从而方便修改一些固定的配置.不明白的可以百度@value的详解. 配置@value有以下几个步骤. 1.首 ...

  4. 如何在html添加一个搜索框和一个按钮?

    <INPUT TYPE="text" id="k"><INPUT TYPE="button" VALUE="ok ...

  5. Oracle导出的sql执行出错

    建的表如果有constraint的话sql语句中会有create unique index...而在前面的建表语句中,这个index实际上已经建好了. 所以导出的sql语句,应该将后面的create ...

  6. 类型解释器——C专家编程读书笔记

    对于声明,应该按下面的步骤来进行解释: 1) 声明从它的名字开始读取,然后按照优先级顺序依次读取 2) 优先级顺序 a) 括号括起来的部分 b) 后缀操作符,()表示函数,[]表示数组 c) 前缀操作 ...

  7. Poj(1325),最小点覆盖

    题目链接:http://poj.org/problem?id=1325 Machine Schedule Time Limit: 1000MS   Memory Limit: 10000K Total ...

  8. nginx 的限制连接模块limit_zone与limit_req_zone

    转载于:http://storysky.blog.51cto.com/628458/642970/ nginx 上有两个限制连接的模块一个是 limit_zone 另一个是 limie_req_zon ...

  9. springmvc配置文件-2

    项目3 WEB.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi= ...

  10. ubuntu截屏

    按下键盘上的 PrintScreen 键保存全屏截图 按下 Alt+PrintScreen 快捷键截取当前窗口 按下 Shift+PrintScreen 快捷键截取任意矩形内容