信号驱动式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. Shell基础学习(六) 流程控制

    1.if if的语法格式 if conditon then command1 command2 ``` commandn fi 2.if else if conditon then command1 ...

  2. CentOS 6.9下的iptables在本机用DNAT转发指定IP到内网IP无效的问题解决(127.0.0.1)

    比如: iptables -t nat -A OUTPUT -p tcp -d 192.168.1.0/24 --dport 2222 -j DNAT --to-destination 127.0.0 ...

  3. Android的Master/Detail风格界面中实现自定义ListView的单选

    原文在这里:http://duduli.iteye.com/blog/1453576 可以实现多选,那么如何实现单选呢,这里我写了一个非常简单的方法: public void onListItemCl ...

  4. VC中__int64的用法

    VCVC6.0的64位整数分别叫做__int64与unsigned __int64,其范围分别是[-2^63, 2^63)与[0,2^64),即-922337203685 4775808~922337 ...

  5. BusyBox 简化嵌入式 Linux 系统

    BusyBox 是很多标准 Linux® 工具的一个单个可执行实现.BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大.更复杂的工具,例如 grep.find.moun ...

  6. Replace Pioneer 试用推广

    Replace Pioneer: http://www.mind-pioneer.com 目前合法长期使用Replace Pioneer的唯一方法(除了购买之外): Replace Pioneer过期 ...

  7. java自动识别上传的apk版本号

    import java.util.List; public class ApkInfo { private String versionCode; private String versionName ...

  8. [翻译] Canvas 不用写代码的动画

    Canvas 不用写代码的动画 https://github.com/CanvasPod/Canvas Canvas is a project to simplify iOS development ...

  9. 深度学习Deep learning

    In the last chapter we learned that deep neural networks are often much harder to train than shallow ...

  10. VS2010 OpenCL运行环境配置

    1.安装AMD GPU显卡驱动(安装后重启) 13-12_win7_win8_64_dd_ccc_whql.exe 2.安装AMD OpenCL SDK(安装后重启) AMD-APP-SDK-v2.9 ...