可以将信号注册进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. 【转】详细讲解Java中log4j的使用方法

    转载地址:http://www.233.com/Java/zhuangye/20070731/142625631.html 1.Log4j是什么? Log4j可以帮助调试(有时候debug是发挥不了作 ...

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

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

  3. python-学习笔记之-Day5 双层装饰器 字符串格式化 python模块 递归 生成器 迭代器 序列化

    1.双层装饰器 #!/usr/bin/env python # -*- coding: utf-8 -*- # author:zml LOGIN_INFO = False IS_ADMIN = Fal ...

  4. WF3.0 CallExternalMethod使用技巧

    CallExternalMethod用于工作流向宿主进程中通信 简单的介绍一下它的使用技巧,参照网上的一个questioner源码进行了改进,因为我感觉这个源码提供的通信demo过于繁琐. 看看ser ...

  5. vs智能提示突然消失的解决办法 (vs2008 vs2010 vs2012 智能提示)

    vs智能提示突然消失的解决办法 (vs2008 vs2010 vs2012 智能提示) 下面一段话是网上找到的解决方案: 重置Visual Studio可以解决此问题,方法是从开始->Micro ...

  6. Reading package lists... Error! 解决方案

    ubuntu 下安装python开发包,执行命令 sudo apt-get install python-dev,报错: Reading package lists... Error! E: Enco ...

  7. readDouble

    readDouble是从一个文件中读取double类型的数据

  8. Testing Round #12 A

    A. Divisibility time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  9. android导入项目出现style错误,menu错误

    android导入项目出现style错误,menu错误 style //查看 res/values/styles.xml 下的报错点. <style name="AppBaseThem ...

  10. 多线程&NSObject&NSThread&NSOperation&GCD

    1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 2.NSOperation/NS ...