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. 为什么不要使用 Async Void ?

    原文:为什么不要使用 Async Void ? 问题 在使用 Abp 框架的后台作业时,当后台作业抛出异常,会导致整个程序崩溃.在 Abp 框架的底层执行后台作业的时候,有 try/catch 语句块 ...

  2. java程序——输入判断成绩

    import java.util.*; class ExceptionOut extends Exception{ } public class Score { public static void ...

  3. iOS 引用外部静态库(.a文件)时或打包.a时,Category方法无法调用。崩溃

    我的这个是MJRefresh,学习打.a包Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ...

  4. 【APUE】Chapter12 Thread Control

    今天看了APUE的Chapter12 Thread Control的内容,记录一下看书的心得与示例code. 这一章的内容是对Chapter11 Threads(见上一篇日志)的补充,大部分内容都是理 ...

  5. Kotlin中功能操作与集合(KAD 11)

    作者:Antonio Leiva 时间:Feb 2, 2017 原文链接:https://antonioleiva.com/functional-operations-collections-kotl ...

  6. docker部署思路

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

  7. Opencv2.4.13.6安装包

    这个资源是Opencv2.4.13.6安装包,包括Windows软件包,Android软件包,IOS软件包,还有opencv的源代码:需要的下载吧. 点击下载

  8. 聊聊、Mybatis XML

    引入相应的依赖包 <dependency><groupId>org.mybatis</groupId><artifactId>mybatis-sprin ...

  9. HDU 4031 Attack (线段树)

    成功袭击次数=所有袭击次数-成功防守次数 需要一个辅助pre来记录上一次袭击成功什么时候,对于每个查询,从上一次袭击成功开始,每隔t更新一次. 感觉这样做最坏时间复杂度是O(n^2),这里 说是O(q ...

  10. 团队项目-第一次Scrum 会议

    时间:10.23 时长:30分钟 地点:F楼2层沙发休息处 工作情况 团队成员 已完成任务 待完成任务 解小锐 学习使用cocos creator 学习官方样例 陈鑫 学习JavaScript 学习c ...