前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TCP/IP网络编程之I/O复用select函数

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

作者头像
用户2825413
发布2019-07-15 20:23:46
9270
发布2019-07-15 20:23:46
举报

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

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

多进程服务模型:
I/O 复用进程模型:

select 实现I/O 复用

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

代码语言:javascript
复制
#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

参数解释:

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

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

文件描述符管理

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

代码语言:javascript
复制
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 超时设置结构体
代码语言:javascript
复制
struct timeval 
{
    long tv_sec;  //seconds
    long tv_usec; //microseconds
}
select函数执行前后示例图
示例代码(回声)

select.c

代码语言:javascript
复制
#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);
            }
        }
    }
}

执行输出

代码语言:javascript
复制
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
本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-19,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 呆呆熊的技术路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 多进程服务模型:
  • I/O 复用进程模型:
  • select 实现I/O 复用
    • 文件描述符管理
      • timeval 超时设置结构体
        • select函数执行前后示例图
          • 示例代码(回声)
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
          http://www.vxiaotou.com