socket信号驱动

为了使一个套接字能够使用信号驱动I/O,至少需要以下3步操作。

  • 1.安装SIGIO信号
  • 2.套接字的拥有者设定为当前进程。因为SIGIO信号只会送到socket拥有者进程. 通过fcntl的F_SETOWN
  • 3.套接字必须被允许使用异步I/O。 通过fcntl的F_SETFL,设置为O_ASYNC

在UDP通信中,下面情况会产生SIGIO信号

在TCP通信中,下面情况会产生SIGIO信号

例子:

下面的代码好奇怪,说是UDP的,但是发送接收用的是send, recv 而且客户端还跟服务器连接了;说是TCP,但是socket建立的时候用的是SOCK_DGRAM.

而且代码是可以跑通的。

服务器:

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<netdb.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/ioctl.h>
#define MAX_LENTH 1500 //针对SIGIO信号处理
static int nqueue = ;
void sigio_handler(int signum)
{
if(signum == SIGIO)
nqueue++;
printf("signum = %d, nqueue = %d\n", signum, nqueue); //打印信号值
return;
}
static recv_buf[MAX_LENTH]; int main(int argc, char *argv[])
{
int sockfd, on = ;
struct sigaction action;
sigset_t newmask, oldmask;
struct sockaddr_in ser_addr;
if(argc != )
{
printf("use: %s ip_add port\n", argv[]);
exit(EXIT_FAILURE);
} memset(&ser_addr, , sizeof(ser_addr));
ser_addr.sin_family = AF_INET; //使用IPv4
ser_addr.sin_port = htons(atoi(argv[]));
if(inet_aton(argv[], (struct in_addr *)&ser_addr.sin_addr.s_addr) == )
{
perror(argv[]);
exit(EXIT_FAILURE);
}
//创建socket
if((sockfd = socket(AF_INET, SOCK_DGRAM, )) == -)
{
perror("socket");
exit(EXIT_FAILURE);
}
//绑定IP地址
if(bind(sockfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -)
{
perror("bind");
exit(EXIT_FAILURE);
}
memset(&action, , sizeof(action));
action.sa_handler = sigio_handler;
action.sa_flags = ;
//安装信号
sigaction(SIGIO, &action, NULL);
//设置socket拥有者
if(fcntl(sockfd, F_SETOWN, getpid()) == -)
{
perror("fcntl F_SETOWN");
exit(EXIT_FAILURE);
}
//设置socket为信号驱动型
if(ioctl(sockfd, FIOASYNC, &on) == -)
{
perror("ioctl FIOASYNC");
exit(EXIT_FAILURE);
}
sigemptyset(&oldmask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGIO);
printf("get ready\n");
while()
{
int len;
//设置当前阻塞的信号
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
//等待信号
while(nqueue == )
sigsuspend(&oldmask);
memset(recv_buf, '\0', MAX_LENTH);
//非阻塞接收数据
len = recv(sockfd, recv_buf, MAX_LENTH, MSG_DONTWAIT);
if(len == - && errno == EAGAIN)
nqueue = ;
//修改进程阻塞的信号
sigprocmask(SIG_SETMASK, &oldmask, NULL);
if(len >= )
printf("recv %d byte, msg is %s\n", len, recv_buf);
} }

客户端

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<netdb.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/ioctl.h>
#define MAX_LENTH 1500 int main(int argc, char *argv[])
{
struct sockaddr_in addr;
int sock_fd, ret;
char snd_buf[MAX_LENTH];
if(argc != ) //参数需要服务器的IP和端口
{
printf("use: %s ip_add port\n", argv[]);
exit(EXIT_FAILURE);
}
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
if(inet_aton(argv[], (struct in_addr *)&addr.sin_addr.s_addr) == )
{
perror(argv[]);
exit(EXIT_FAILURE);
}
addr.sin_port = htons(atoi(argv[]));
//创建socket
if((sock_fd = socket(AF_INET, SOCK_DGRAM, )) == -)
{
perror("socket");
exit(EXIT_FAILURE);
}
//向服务器发起连接 ??这不是TCP的么
if(ret = connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == -)
{
perror("connect");
exit(EXIT_FAILURE);
}
while()
{
printf("input msg to send:");
memset(snd_buf, '\0', MAX_LENTH);
fgets(snd_buf, MAX_LENTH - , stdin);
write(sock_fd, snd_buf, MAX_LENTH - );
}
}

【linux高级程序设计】(第十五章)UDP网络编程应用 4的更多相关文章

  1. 读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

    读书笔记 - js高级程序设计 - 第十三章 事件   canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好   有时候即使浏览器支持,操作系统如果缺缺 ...

  2. JavaScript高级程序设计:第五章

    引用类型 一.object类型: 创建object实例的方式有两种.第一种是使用new操作符后跟Object构造函数,如下所示: var  person = new  Object(): person ...

  3. 《javascript高级程序设计》第五章 reference types

    第5 章 引用类型5.1 Object 类型5.2 Array 类型 5.2.1 检测数组 5.2.2 转换方法 5.2.3 栈方法 5.2.4 队列方法 5.2.5 重排序方法 5.2.6 操作方法 ...

  4. 【linux高级程序设计】(第九章)进程间通信-管道 1

    Linux操作系统所支持的主要进程间的通信机制. 无名管道 PIPE cat test.txt| grep hello 上面这种管道,将一个命令的输出作为另一个命令的输入,而这种管道是临时的,命令执行 ...

  5. linux高级管理第十二章--rsync

    实验部分 1.安装rsync 2.配置文件 3.配置密码 4.后续 5.为了测试,创建几个文件 配置实时同步 1.调整inotify内核参数 安装inotify-tools 测试同步 编写脚本 验证 ...

  6. 《JAVASCRIPT高级程序设计》第五章(2)

    一.Date类型 Date类型类型用于保存日期,有以下几种创建方式: //获取当前时间 var now = new Date(); //获取当前时间的毫秒数 var nowSecond = Date. ...

  7. 《JAVASCRIPT高级程序设计》第五章(1)

    引用类型是一种将数据和功能组合到一起的数据结构,它与类相似,但是是不同的概念:ECMAScript虽然是一门面向对象的语言,但它不具备传统的面向对象语言所支持的类和结构等基本结构.引用类型也被称为“对 ...

  8. Javascript高级程序设计笔记 <第五章> 引用类型

    一.object类型 创建object实例的方式有两种: //第一种使用new操作符跟构造函数 var person= new Object(); person.name="小王" ...

  9. Javascript高级程序设计复习——第五章引用类型 【原创】

    5.1  Object类型 1:创建Object实例的两种方式 ①new构造法 var obj1 = new Object(); 注意大写!不传递参数时可以省略圆括号 obj1.hehe = &quo ...

  10. Linux高级运维 第五章 Vim编辑器和恢复ext4下误删除的文件-Xmanager工具

    5.1  vim主要模式介绍,vim命令模式. 确保系统已经安装了VIM工具 [root@panda ~]# rpm -qf `which vim` [root@panda ~]# rpm -qf ` ...

随机推荐

  1. Android MultiType第三方库的基本使用和案例+DiffUtil的简单用法

    1.MultiType简单介绍 1.1.MultiType用于比较复杂的页面. 如下图,今日头条用到了MultiType处理各种复杂的页面.    这种还是比较简单的类型.因为一个页面也就这种类型. ...

  2. Linux下添加桌面快捷方式

    这里用Ubuntu下BurpSuite举例 sudo vim /home/user/Desktop/burpsuite.desktop //burpsuite随意起名,系统会系动创建文件 文件写入 # ...

  3. android onNewIntent 为什么要在onNewIntent的时候要显示的去调用setIntent

    原因: 当调用到onNewIntent(intent)的时候,需要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.否则,后续的getInte ...

  4. Centos 7.X 安装JDK1.8

    一.查看本机jdk版本并卸载原有openjdk        查看       # java -version       openjdk version "1.8.0_144"  ...

  5. 关于代码通过API操作阿里云RDS的巨坑

    由于项目原因,要通过API操作阿里云的数据库,于是简单研究了一下阿里云提供的相关文档,发现官方提供了.NET的SDK,而且还提供了github开源代码,这个要为阿里点赞! 于是到github上弄了一份 ...

  6. HDU 4747 Mex ( 线段树好题 + 思路 )

    参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...

  7. 剑指offer:二维数组中的查找

    目录 题目 解题思路 具体代码 题目 题目链接 剑指offer:二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺 ...

  8. PHP文件开头session_start()

    session_start(); 告诉服务器使用session.一般来说,php是不会主动使用session的. 不过可以设置php.ini中的session.auto_start=1来自动对每个请求 ...

  9. 二、vue响应式对象

    Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Obj ...

  10. 叶落归根(hometown)

    叶落归根(hometown) 题目描述 叶落归根——树叶从树根生发出来,凋落后最终还是回到树根.比喻事物总有一定的归宿.接下来是题目. 给定一个n个点的有向图G(点的编号为1~n),一开始落叶(仅作为 ...