信号驱动式I/O的本质就是:进程预先告知内核当某个描写叙述符发生事件时,内核会向该进程发送SIGIO信号通知进程,进程可在信号处理函数中进行处理





进程能够通过fcntl打开O_ASYNC标志或ioctl打开FIOASYNC标志来通知内核,二者的差别是一些系统不支持fcntl,所以应尽量使用ioctl





对于TCP套接字产生SIGIO信号的条件:

1.监听套接字上有新连接请求完毕

2.某个断连请求发起

3.某个断连请求完毕

4.数据到达套接字

5.数据已从套接字发送走(输出缓冲区有空暇空间)

6.发生某个异步错误





对于UDP套接字产生SIGIO信号的条件:

1.数据报到达套接字

2.套接字上发生异步错误





对于套接字而言:TCP套接字和UDP套接字致使内核产生SIGIO信号的条件有所不同,当中TCP可产生该信号的条件较多,而UDP套接字产生该信号的条件仅仅有两个,由于我们无法得知详细是什么事件导致内核产生该信号。

。对于UDP套接字产生该信号条件的推断就简单的多。这也是信号驱动式I/O主要用于UDP套接字的原因。

套接字使用信号驱动式I/O的步骤:

1.建立SIGIO信号处理函数

2.设置设置套接字属主(使用fcntl的F_SETOWN命令)

3.开启信号驱动式I/O(fcntl打开O_ASYNC 或 ioctl打开FIOASYNC)





实例:

客户每隔1秒钟将系统时间发送到server,server通过SIGIO信号处理函数中接收数据

net.h

#ifndef MY_NET_H
#define MY_NET_H #include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <iostream>
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h> using namespace std; char recvBuf[1025];
int listenfd; static void sigio_handler(int signo)
{
if (signo != SIGIO)
return; int ret;
while (1)
{
ret = recvfrom(listenfd, recvBuf, sizeof(recvBuf),
0, NULL, NULL);
if (ret < 0)
{
if (errno == EWOULDBLOCK)
break; perror("recvfrom error");
exit(-1);
} cout << recvBuf << endl;
}
} void init(int skfd)
{
int ret; //1.建立SIGIO信号的处理函数
signal(SIGIO, sigio_handler); //2.设置该套接字的属主
ret = fcntl(skfd, F_SETOWN, getpid());
if (ret < 0)
{
perror("fcntl error");
exit(-1);
} //3.开启该套接字的信号驱动式I/O
int on = 1;
ret = ioctl(skfd, FIOASYNC, &on);
if (ret < 0)
{
perror("ioctl error");
exit(-1);
}
} int prepare()
{
int skfd = socket(AF_INET, SOCK_DGRAM, 0);
if (skfd < 0)
return -1; struct sockaddr_in saddr;
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(9999);
saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(skfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0)
return -1; return skfd;
} #endif

客户:

#include "net.h"

int main()
{
int skfd;
skfd = socket(AF_INET, SOCK_DGRAM, 0);
if (skfd < 0)
{
perror("socket error");
exit(-1);
} int ret;
time_t tm;
struct sockaddr_in desAddr;
bzero(&desAddr, sizeof(desAddr));
desAddr.sin_family = AF_INET;
desAddr.sin_port = htons(9999);
desAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); while (1)
{
time(&tm);
ret = sendto(skfd, ctime(&tm), strlen(ctime(&tm)), 0,
(struct sockaddr*)&desAddr, sizeof(desAddr));
if (ret < 0)
{
perror("");
exit(-1);
}
sleep(1);
} return 0;
}

server:

#include "net.h"

int main()
{
listenfd = prepare();
if (listenfd < 0)
{
perror("prepare error");
exit(-1);
} init(listenfd);
while(1); return 0;
}

udp套接字使用信号驱动式I/O的更多相关文章

  1. UNIX网络编程——信号驱动式I/O

    信号驱动式I/O是指进程预先告知内核,使得当某个描述符上发生某事时,内核使用信号通知相关进程. 针对一个套接字使用信号驱动式I/O,要求进程执行以下3个步骤: 建立SIGIO信号的信号处理函数. 设置 ...

  2. UNP学习笔记(第二十五章 信号驱动式I/O)

    信号驱动式I/O是指进程预先告知内核,使得当某个描述符发生某事时,内核使用信号通知相关进程. 套接字的信号驱动式I/O 针对一个套接字使用信号驱动式I/O(SIGIO)要求进程执行以下3个步骤: 1. ...

  3. 信号驱动式I/O

    信号驱动式I/O是指进程预先告知内核,使得当某个描述符上发生某事时,内核使用信号通知相关进程. 异步I/O是进程执行I/O系统调用(读或写)告知内核启动某个I/O操作,内核启动I/O操作后立刻返回到进 ...

  4. 计算机网络实验 UDP套接字编程

    这是个傻瓜式操作教程 西科大计算机网络实验 UDP套接字编程 我用自己的Ubuntu16.04来举例,实验室的是虚拟机,差不多 只针对第三个题目,修改服务器来通过响应客户端发送的GetTime并发送给 ...

  5. Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输

    一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...

  6. QT下UDP套接字通信——QUdpSocket 简单使用

    QT下UDP套接字通信--QUdpSocket QUdpSocket类提供一个UDP套接字. UDP(用户数据报协议)是一种轻量级.不可靠.面向数据报.无连接的协议.它可以在可靠性不重要的情况下使用. ...

  7. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

  8. 探索UDP套接字编程

    UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...

  9. 【Python网络编程】利用Python进行TCP、UDP套接字编程

    之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...

随机推荐

  1. Android -- 工程目录解释

    src:放置我们编写的源文件 gen:ADT帮助我们生成的,当项目使用资源时,会通过R.java引用资源文件(16进制,不可修改).每当资源发生变化都会重新编译R.java android x.x:我 ...

  2. [转]Eclipse 项目转移到Android Studio遇到的问题

    1.Android Studio直接导入项目是copy原项目的,无法纳入代码管控 解决方案: 英文地址:http://developer.android.com/sdk/installing/migr ...

  3. MYSQL学习笔记 (五)常用的聚合函数

    1.COUNT(e1) 语法:COUNT(e1) 参数:e1为一个表达式,可以是任意的数据类型 返回:返回数值型数据 作用:返回e1指定列不为空的记录总数 例子: 1)单独使用

  4. 深入浅出JDBC-操作时间与大对象(Clob/Blob)

    一.时间(Date.Time.Timestamp) java.sql.Date/java.sql.Time/java.sql.Timestamp extends java.util.Date publ ...

  5. C#如何用OpenFileDialog控件打开图片显示到PictureBox这个控件

    openFileDialog1.Filter = "图片文件|*.jpg|BMP图片|*.bmp|Gif图片|*.gif"; OpenFileDialog ofd = new Op ...

  6. 通过手机音频口,实现与单片机通讯,做电子签名成功n

    手机端的Ukey便携产品, 可以管理证书.加密解密.电子签名 : 1.通讯稳定,生成签名成功率100% 2.证书固化,私钥安全 3.走手机音频接口,通用.跨平台 4.耗电少,自带电池可长期供电,且可充 ...

  7. 发展中的生命力——Leo鉴书69

    接触<寻路中国>是在2011年11月24号的正略读书会上.当期主讲嘉宾是万圣书园创始人刘苏里,也是著名的大书评人.读书会有个传统就是每期推荐一本书.当期推荐就是<寻路中国>.事 ...

  8. java Integer包装类装箱的一个细节

    原文:https://www.cnblogs.com/JackPn/p/9392145.html java有八个基本数据类型,每个都有对应的一个包装类,比如int对应的Integer.从jdk1.5开 ...

  9. UIButton 设置圆角 边框颜色 点击回调方法

    UIButton *signBtn = [UIButton buttonWithType:UIButtonTypeCustom]; signBtn.frame = CGRectMake(, , , ) ...

  10. 纠正jQuery获取radio选中值的写法

    先看一段代码 <input type="radio" name="aaa" value="1" checked="true& ...