专栏首页呆呆熊的技术路TCP/IP网络编程之I/O复用select函数

TCP/IP网络编程之I/O复用select函数

之前我们使用了几种服务器模型,一个是单进程的, 同一时刻只能给一个客户端提供服务, 后来我们使用了多进程, 每个客户端fork新进程进行请求处理

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程,可以使用一个进程服务多个客户端.

多进程服务模型:

I/O 复用进程模型:

select 实现I/O 复用

select实现比较简单,主要使用select函数 函数原型:

#include <sys/select.h>
#include <sys/time.h>

int select(int maxfd, fd_set * readset, fd_set * writeset, fd_set * exceptset, const struct timeval * timeout);

成功时返回大于0的值, 失败时返回 -1

参数解释:

maxfd 监视对象文件描述符的数量,举例写法 sever_sock+1
readset 存储的待读取数据文件描述符
writeset 可传输无阻塞数据文件描述符 
exceptset 发生异常的文件描述符
timeout 超时设置

select函数返回值, 如果返回大于0的整数, 说明相应数量的文件描述符发生了变化.

文件描述符管理

我们发现在 参数类型上有 fd_set类型,这是什么类型呢? fd_set结构是文件描述符对应的位存储数据格式, 当我们管理这些监控的文件描述符时, 可以以下宏来实现

FD_ZERO(fd_set * fdset) 
将 fd_set 变量的所有位初始化位0

FD_SET(int fd, fd_set * fdset)
在参数 fd_set 指向的变量中注册文件描述符 fd 的信息

FD_CLR(int fd, fd_set * fdset)
从参数 fdset 指向的变量中清除文件描述符 fd 的信息

FD_ISSET(int fd, fd_set * fdset) 
若参数 fdset  指向的变量中包含文件描述符 fd 的信息,则返回真

timeval 超时设置结构体

struct timeval 
{
    long tv_sec;  //seconds
    long tv_usec; //microseconds
}

select函数执行前后示例图

示例代码(回声)

select.c

#include <stdio.h>
#include <sys/select.h>

#define BUF_SIZE 1024

int main(int argc, char *argv[])
{
    //监视的文件描述符
    fd_set reads, temps;
    struct timeval timeout;
    int result, str_len;
    char buf[BUF_SIZE];

    FD_ZERO(&reads);
    FD_SET(0, &reads); //0 is standard input(console)

    while (1)
    {
        //因为每次select会重置监控句柄,所以赋值给临时
        temps = reads;

        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        // puts 只有事件发生或者发生超时才执行,否则select阻塞
        puts("xxxx");
        result = select(1, &temps, 0, 0, &timeout);

        if (result == -1)
        {
            puts("select() error");
        }
        else if (result == 0)
        {
            puts("nothing event change..time out");
        }
        else
        {
            if (FD_ISSET(0, &temps))
            {
                str_len = read(0, buf, BUF_SIZE);
                printf("message from consle: %s\n", buf);
            }
        }
    }
}

执行输出

gcc select.c -o select

./select
xxxx
123456
message from consle: 123456

xxxx
7890ha
message from consle: 7890ha

xxxx
nothing event change..time out
xxxx
777
message from consle: 777

xxxx
^C

本文分享自微信公众号 - 呆呆熊的技术路(gh_93f28f51010a),作者:呆呆

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式第五讲-适配器模式

    存在两种适配器: “对象适配器” 和 “类”适配器 (因为大部分语言不支持多重继承,所以此处指的是对象适配器)

    用户2825413
  • 《百万级并发商品服务架构解密》读后总结

    最近看了一个技术分享的视频《百万级并发商品服务架构解密》, 演讲者来自 网易考拉的丁鸣亮, 感觉讲的还不错, 根据内容简单整理如下(商品详情案例):

    用户2825413
  • 设计模式第七讲-责任链模式

    责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系

    用户2825413
  • Linux select 一网打尽

    注:本文的所有内容均指针对 Linux Kernel, 当前使用的源码版本是 5.3.0

    扫帚的影子
  • java nio 在windows的实现

    参考java nio 在windows上的实现 很多人说是IOCP,其实是select。 首先我们一步步查看调用链: Selector.select->....

    平凡的学生族
  • Kafka-14.实现

    有两个分区的名为“my_topic”的主题的日志包含两个目录(即my_topic_0和my_topic_1),其中填充了包含该主题的消息的数据文件。日志文件的格...

    悠扬前奏
  • 分布式架构的套路No.74

    今天小蕉跟大伙一起聊聊分布式系统的架构的套路。在开始说套路之前,大家先思考一个问题,为什么要进行分布式架构? 大多数的开发者大多数的系统可能从来没接触过分布式...

    大蕉
  • linux使用vi中文乱码的解决办法

    set encoding=GB2312 set fileencoding=GB2312

    一见
  • 读《Java编程思想》

    虽千万人,吾往矣 2016-09-14 Java编程思想是一本对于初级程序员来说较高端的入门书。 他有两个特点: 在容器以及并发编程方面不深入,对于一些技术点...

    于霆霖
  • 分布式架构的套路No.74

    今天小蕉跟大伙一起聊聊分布式系统的架构的套路。在开始说套路之前,大家先思考一个问题,为什么要进行分布式架构? 大多数的开发者大多数的系统可能从来没接触过分布式系...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券