网络编程及io多路复用

发布于:2024-09-18 ⋅ 阅读:(130) ⋅ 点赞:(0)

poll函数:

通过man手册查到poll的参数及用法:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

功能: 监视并等待多个文件描述符的属性变化

参数:

1.struct pollfd *fds: 关心的文件描述符数组,大小自己定义

2. nfds: 最大文件描述符个数

3. timeout: 超时检测 (毫秒级):如果-1,阻塞 如果0,不阻塞。

返回值: <0 出错 >0 表示有事件产生;

特点:

  1. 非阻塞和阻塞模式: 可以在阻塞模式下等待事件发生,或者设置超时时间后返回。poll
  2. 适用文件描述符: 可以监视多个文件描述符,包括套接字、文件和设备等。
  3. 使用结构体: 通过 结构体数组传递文件描述符和事件信息。pollfd
  4. 更高效的处理: 适合处理大量文件描述符,相较于 在文件描述符较多时更高效。select
  5. 支持事件类型: 可以监听多种事件类型,如可读、可写和异常条件等。

用代码实现:输入键盘事件

#include <stdio.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    int ret;
    char buf[128] = {0}; // 用于存储读取的数据
    int fd = open("/dev/input/mouse0", O_RDONLY); // 打开鼠标设备文件
    if (fd < 0)
    {
        perror("open err"); // 打开文件出错
        return -1;
    }
    // 1. 创建结构体数组
    struct pollfd fds[2];
    // 2. 配置第一个文件描述符(标准输入)
    fds[0].fd = 0;          // 文件描述符0代表标准输入(键盘)
    fds[0].events = POLLIN; // 关注的事件类型是可读事件
    // fds[0].revents=;// 实际发生的事件(会在poll调用后更新)
    // 3. 配置第二个文件描述符(鼠标设备)
    fds[1].fd = fd;
    fds[1].events = POLLIN; // 关注的事件类型是可读事件
    // 4. 保存数组内最后一个有效元素的下标
    int last = 1;
    // 5. 调用poll函数,监听文件描述符事件
    while (1)
    {
        ret = poll(fds, last + 1, 2000); // 2000毫秒超时
        if (ret < 0)
        {
            perror("poll err"); // poll出错
            return -1;
        }
        else if (ret == 0)
        {
            printf("time out\n"); // 超时无事件发生
        }
        
        // 6. 判断文件描述符实际触发的事件
        if (fds[0].revents & POLLIN)
        {
            // 7. 处理标准输入(键盘)事件
            fgets(buf, sizeof(buf), stdin); // 从标准输入读取数据
            printf("keybroad:%s\n", buf); // 打印键盘输入
        }
        if (fds[1].revents & POLLIN)
        {
            // 8. 处理鼠标设备事件
            ssize_t n = read(fd, buf, sizeof(buf)); // 从鼠标设备读取数据
            if (n > 0)
            {
                printf("mouse: ");
                for (ssize_t i = 0; i < n; ++i)
                {
                    printf("%02x ", (unsigned char)buf[i]); // 打印鼠标数据
                }
                printf("\n");
            }
        }
        memset(buf, 0, sizeof(buf)); // 清空缓冲区
    }

    close(fd); // 关闭文件描述符
    return 0;
}

,响应键盘事件,输入鼠标事件,响应鼠标事件(两路IO)

思路:

  1. 打开文件描述符:程序打开了标准输入和一个鼠标设备文件的文件描述符。
  2. 配置 pollfd 结构体:设置 结构体来关注这些文件描述符上的可读事件。pollfd
  3. 调用 poll:在循环中调用 以等待事件发生,设置超时时间为2000毫秒。poll
  4. 处理事件:根据 字段的值处理标准输入(键盘输入)和鼠标设备的事件。revents
  5. 读取和输出数据:从文件描述符读取数据并输出到控制台。
  6. 清理:循环结束后关闭文件描述符。

代码:


网站公告

今日签到

点亮在社区的每一天
去签到