poll函数测试

2023-05-16

一 基础知识 

     #include <poll.h>
     int poll(struct pollfd *fds, nfds_t nfds, int timeout);

其中参数fds指向一个结构体数组的第0个元素的指针,每个数组元素都是一个struct pollfd结构,用于指定测试某个给定的fd的条件;参数nfds用来指定第一个参数数组元素个数;timeout用于指定等待的毫秒数,无论I/O是否准备好,poll都会返回,如果timeout赋值为‒1则表示永远等待,直到事件发生;如果赋值为0,则表示立即返回;如果赋值为大于0的数,则表示等待指定数目的毫秒数。如果函数执行成功,则返回结构体中revents域不为0的文件描述符个数,如果在超时前没有任何事件发生,则函数返回0;如果函数执行失败,则返回‒1,并设置errno为下列值之一:

· EBADF:一个或多个结构体中指定的文件描述符无效。

· EFAULT:fds指针指向的地址超出进程的地址空间。

· EINTR:请求的事件之前产生一个信号,调用可以重新发起。

· EINVAL:nfds参数超出PLIMIT_NOFILE值。

· ENOMEM:可用内存不足,无法完成请求。

结构体pollfd定义如下:

       struct pollfd{
          int fd;         //文件描述符
          short events;   //等待的事件
          short revents;  //实际发生的事件
       };

其中字段fd表示每一个pollfd结构体指定了一个被监视的文件描述符,可以传递多个结构体,指示poll监视多个文件描述符;events指定监测fd的事件(输入、输出、错误),每一个事件有多个取值,如图所示。

 测试代码:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
// #include <sys/epoll.h>
#include <poll.h>
#include <errno.h>
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
#define BUFFER_SIZE 1024

void set_nonblock(int fd){
    int flag = fcntl(fd,F_GETFL);
    if(flag == -1){
        perror("set_nonblock");
        exit(1);
    }
    flag |= O_NONBLOCK;
    if(fcntl(fd,F_SETFL, flag) < 0){
        perror("fcntl");
        exit(1);
    }
}

#define MAX_EVENT_NUMBER 100
struct pollfd pollfds[MAX_EVENT_NUMBER];
char buf[BUFFER_SIZE];

int init_fds(struct pollfd*fds,int count){
    for(int i = 0; i < count; i++){
        fds[i].fd = -1;
        fds[i].events = 0;
        fds[i].revents = 0;
    }
}
int insert_fd(struct pollfd*fds,int count,int fd,int events){
    for(int i = 0; i < count; i++){
        if(fds[i].fd == -1){
            fds[i].fd = fd;
            fds[i].events = events;
            fds[i].revents = 0;
            DEBUG_INFO("insert ok,fd = %d,i = %d",fd,i);
            return 0;
        }        
    }
    DEBUG_INFO("insert error");
    return -1;
}
int delete_fd(struct pollfd*fds,int count,int fd){
    for(int i = 0; i < count; i++){
        if(fds[i].fd == fd){
            fds[i].fd = -1;
            fds[i].events = 0;
            fds[i].revents = 0;
            DEBUG_INFO("delete ok,fd = %d,i = %d",fd,i);
            return 0;
        }        
    }
    DEBUG_INFO("delete error");
    return -1;
}

void test_01(){
    int listenfd;
    int on = 1;
    struct sockaddr_in server_addr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,&on,sizeof(on)) < 0){
        perror("setsockopt");
        exit(-1);
    }
    DEBUG_INFO("begin bing");
    server_addr.sin_port = htons(9878);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    if(bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){
        perror("bind");
        exit(0);
    }
    listen(listenfd,5);

    set_nonblock(listenfd);
    
    init_fds(pollfds,MAX_EVENT_NUMBER);
    insert_fd(pollfds,MAX_EVENT_NUMBER,listenfd,POLLIN);

    DEBUG_INFO("poll");
    int fd_count = 1;
    while(1){
        int ret = poll(pollfds,MAX_EVENT_NUMBER,-1 );
        if(ret == -1){
            perror("poll");
            exit(0);
        }
        for(int i = 0;i < MAX_EVENT_NUMBER;i++){
            if(pollfds[i].fd == -1){
                continue;
            }
            if(!(pollfds[i].revents & POLLIN)){
                continue;
            }
            if(pollfds[i].fd == listenfd){
                struct sockaddr_in client;
                socklen_t addrlen = sizeof(client);
                int clientfd = accept(listenfd, (struct sockaddr *)&client,&addrlen);
                if(ret == -1){
                    exit(1);
                }
                DEBUG_INFO("new client = %d",clientfd);
                insert_fd(pollfds,MAX_EVENT_NUMBER,clientfd,POLLIN);
                continue;
            }
            if(pollfds[i].revents & POLLIN){
                bzero(buf, sizeof(buf)/sizeof(buf[0]));
                ret = recv(pollfds[i].fd,buf,sizeof(buf)/sizeof(buf[0]),0);
                if(ret > 0){
                    DEBUG_INFO("ret = %d,buf = %s,i = %d,fd = %d",ret,buf,i,pollfds[i].fd);
                    send(pollfds[i].fd,buf,ret,0);
                    continue;
                }
                //close
                if(ret == 0){
                    DEBUG_INFO("close i = %d fd = %d",i,pollfds[i].fd);
                    delete_fd(pollfds,MAX_EVENT_NUMBER,pollfds[i].fd);
                    continue;
                }
                if(ret == -1){
                    //暂时不判断
                    perror("recv");
                    exit(1);
                }
            }
        }

    }
    exit(0);
}

int main(int argc, char **argv)
{
    test_01();
}

测试

创建两个客户端:

 然后反复连接,断开,然后发送数据,就会接收到刚刚发出去的数据。

test_01:125 -- ret = 11,buf = hello world,i = 1,fd = 6
test_01:131 -- close i = 2 fd = 8
delete_fd:61 -- delete ok,fd = 8,i = 2
test_01:117 -- new client = 9
insert_fd:48 -- insert ok,fd = 9,i = 2
test_01:131 -- close i = 2 fd = 9
delete_fd:61 -- delete ok,fd = 9,i = 2
test_01:117 -- new client = 10
insert_fd:48 -- insert ok,fd = 10,i = 2
test_01:131 -- close i = 2 fd = 10
delete_fd:61 -- delete ok,fd = 10,i = 2
test_01:117 -- new client = 11
insert_fd:48 -- insert ok,fd = 11,i = 2
test_01:131 -- close i = 2 fd = 11
delete_fd:61 -- delete ok,fd = 11,i = 2
test_01:117 -- new client = 12
insert_fd:48 -- insert ok,fd = 12,i = 2
test_01:131 -- close i = 2 fd = 12
delete_fd:61 -- delete ok,fd = 12,i = 2
test_01:117 -- new client = 13
insert_fd:48 -- insert ok,fd = 13,i = 2
test_01:131 -- close i = 2 fd = 13
delete_fd:61 -- delete ok,fd = 13,i = 2
test_01:117 -- new client = 14
insert_fd:48 -- insert ok,fd = 14,i = 2
test_01:125 -- ret = 4,buf = gulu,i = 2,fd = 14
test_01:125 -- ret = 4,buf = gulu,i = 2,fd = 14
test_01:125 -- ret = 4,buf = gulu,i = 2,fd = 14
test_01:125 -- ret = 4,buf = gulu,i = 2,fd = 14

小结

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

poll函数测试 的相关文章

随机推荐

  • [gevent源码分析] 深度分析gevent运行流程

    一直对gevent运行流程比较模糊 xff0c 最近看源码略有所得 xff0c 不敢独享 xff0c 故分享之 gevent是一个高性能网络库 xff0c 底层是libevent xff0c 1 0版本之后是libev xff0c 核心是g
  • TCP服务器端和客户端程序设计

    一 实验目的 学习和掌握Linux下的TCP服务器基本原理和基本编程方法 体会TCP与UDP编程的不同 xff0c UDP编程 xff1a http blog csdn net yueguanghaidao article details
  • UDP服务器端和客户端程序设计

    实验三 UDP服务器端程序设计 一 实验目的 学习和掌握Linux下的UDP服务器基本原理和基本编程方法 xff0c 体会与TCP的区别 xff0c TCP编程 xff1a http blog csdn net yueguanghaidao
  • python实现的文本编辑器

    wxpython实现的文本编辑器 效果如下 xff1a 主要功能 xff1a 1 编辑保存文本 xff0c 打开修改文本 2 常用快捷键 xff0c 复制 xff0c 粘贴 xff0c 全选等 3 支持撤销功能 4 支持弹出式菜单 代码如下
  • C语言开发Linux下web服务器(支持GET/POST,SSL,目录显示等)

    这个主要是在CSAPP基础上做的 xff0c 添加了POST xff0c SSL xff0c 目录显示等功能 一 实现功能 xff1a 1 支持GET POST方法 2 支持SSL安全连接即HTTPS 3 支持CGI 4 基于IP地址和掩码
  • sklearn2pmml xgboost缺失值(missing)处理的坑

    sklearn2pmml xgboost缺失值 missing 处理的坑 今天同事在部署xgboost pmml模型时遇到了大坑 xff0c 线上spark预测和本地python预测结果怎么都不对应 xff0c 记录一下处理过程 看了下同事
  • adb导出手机应用到电脑

    简单说一下相关步骤 xff0c 以备不时之需 1 手机开启usb调试 2 Windows系统 Win 43 R打开命令行窗口 xff0c 输入adb devices xff0c 如果连接成功会出现机子的序列号 3 adb shell pm
  • Js作用域与作用域链详解

    一直对Js的作用域有点迷糊 xff0c 今天偶然读到Javascript权威指南 xff0c 立马被吸引住了 xff0c 写的真不错 我看的是第六版本 xff0c 相当的厚 xff0c 大概1000多页 xff0c Js博大精深 xff0c
  • windows10环境下tensorflow安装教程

    楼主最近一直忙着找工作 最近几个月一直all in java 好久没学机器学习 深度学习 前几天突然通知要提交论文中期了 于是赶紧打开电脑 结果发现之前安装的tensorflow居然登陆不上了 折腾了半天 搜过各种csdn博客 一直安装失败
  • 'gbk' codec can't encode character '\xa0'

    从网上抓了一些字节流 xff0c 想打印出来结果发生了一下错误 xff1a UnicodeEncodeError 39 gbk 39 codec can 39 t encode character 39 xbb 39 in position
  • 【Git记录学习】github创建项目以及本地使用(vscode)

    一 github创建空仓库 从github中创建空仓库 在执行完上一步操作后会返回这样的界面 xff0c 包括了一些基本的git操作以及HttpS SSH地址 生成一个readme md文档 xff08 步骤2 Set up下面有蓝色的超链
  • 关于DFT变换含义、公式和具体形式

    原文地址 xff1a http blog sina com cn s blog 7853c3910102v9wd html 这篇文章从实际工程应用的角度 xff0c 记录一下如何计算 xff0c 关于公式 变形和应用 维基百科上的 DFT公
  • 1602显示数字不稳定一直跳动(AD转换)

    程序如下所示 首先说明下 xff0c 此程序为AD转换芯片PCF8591采集电压数据 xff0c 然后送到1602显示 现象 xff1a 1602显示的数字一直频繁的跳动 xff0c 乱花眼 此现象不是一直出现的 xff0c 有时候会出现
  • C++11中的线程类

    前面介绍的线程是利用了POSIX线程库 xff0c 这是传统C C 43 43 程序员使用线程的方式 xff0c 而C 43 43 11提供了语言层面使用线程的方式 C 43 43 11新标准中引入了5个头文件来支持多线程编程 xff0c
  • 4.4.1内核编译

    内核源码下载地址 xff1a https mirrors edge kernel org pub linux kernel v4 x linux 4 4 1 tar gz 安装依赖包 xff1a 报错就装 cp boot config xx
  • fatal error: hugetlbfs.h: No such file or directory

    fatal error hugetlbfs h No such file or directory 解决办法 xff1a sudo apt get update sudo apt get install libhugetlbfs dev
  • WSL下 配置NFS-失败

    配置一个IP地址 xff1a sudo ip addr add 192 168 250 2 24 broadcast 192 168 250 255 dev eth2 sudo apt get install nfs kernel serv
  • OMT 对象模型、动态模型和功能模型

    对象模型描述系统中对象的静态结构 对象之间的关系 对象的属性 对象的操作 对象模型表示静态的 结构上的 系统的 数据 34 特征 对象模型为动态模型和功能模型提供了基本的框架 xff0c 对象模型用包含对象和类的对象图来表示 OMT的对象模
  • 关于epoll的调试的几个问题

    将今天调试的几个小问题点总结下 xff0c 后续遇到再添加 一 将总结的问题点放在最前面 1 epoll wait的maxevents参数 epoll wait的maxevents参数 xff0c 经过测试 xff0c maxevents的
  • poll函数测试

    一 基础知识 include lt poll h gt int poll struct pollfd fds nfds t nfds int timeout 其中参数fds指向一个结构体数组的第0个元素的指针 xff0c 每个数组元素都是一