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. 内置函数--sorted,filter,map

    sorted() 排序函数. 语法: sorted(Iterable, key=None, reverse=False) Iterable: 可迭代对象;  key: 排序规则(排序函数); reve ...

  2. Spring.net Ioc 依赖注入

    控制反转 (Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注 ...

  3. miniui IE对省略号即text-overflow:ellipsis显示不一样的问题

    做miniui项目中发现,IE对文本以英文或数字结尾的是英文的省略号,以汉字结尾的就是中文的省略号.只要将字体变为统一宋体即可解决.即 .mini-grid-cell-inner    {       ...

  4. python 表格存取方法(转)

    xlwt/xlrd库 存Excel文件:(如果存储数据中有字符,那么写法还有点小小的变化) import xlwt workbook = xlwt.Workbook(encoding='utf-8') ...

  5. java.sql.SQLException: Field 'id' doesn't have a default value异常

    在做mybatis插入的时候报了这个错误,百度了下,貌似是因为这个健没有设置值且不是自增类型的. java.sql.SQLException: Field 'id' doesn't have a de ...

  6. Javascript进阶:对象实例属性和方法

    Ecmascript中,Object类型是所有它的实例的基础.换句话说,Object类型所具有的任何属性和方法也同样存在于更具体的对象中. Object的每个实例都具有以下属性和方法,这些都能方便于我 ...

  7. Scrapy使用示例

    很多网站都提供了浏览者本地的天气信息,这些信息是如何获取到的呢,方法有很多种,大多是利用某些网站提供的天气api获取的,也有利用爬虫采集的.本文就介绍如何用Scrapy来采集天气信息(从新浪天气频道采 ...

  8. java初学1

    1.Java主要技术和分支以及应用领域 (1)Java SE Java Platform,Standard Edition,Java SE 以前称为J2SE.它允许开发和部署在桌面.服务器.嵌入式环境 ...

  9. docker部署思路

    1.docker安装2.拉取centos镜像或者Ubuntu镜像 看你用哪个3.使用镜像,run出来一个容器A4.进入容器A,安装uwsgi,把Django部署在下面5.在启动脚本中配置开机自启动脚本 ...

  10. 孤荷凌寒自学python第十八天python变量的作用范围

    孤荷凌寒自学python第十八天python函数的形参与变量的范围 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.在python的函数中各种不同的形式参数在定义的先后顺序上有规定: 必须 ...