文档章节

poll 示例

for。
 for。
发布于 2016/07/04 22:28
字数 418
阅读 46
收藏 1
点赞 0
评论 0

poll 使用的结构体如下

struct pollfd {
    int   fd;         /* file descriptor */
    short events;     /* requested events */
    short revents;    /* returned events */
};

需要使用该结构体数组对文件描述符进行注册,poll 通过该数组返回结果。事件就绪时需要遍历所有注册的文件描述符。

源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/stropts.h>

#define SERV_PORT   9000
#define LISTENQ     10
#define OPEN_MAX    1024
#define MAXLINE     1024

int main(int argc, char **argv)
{
    int         listenfd, connfd, sockfd;
    int         nready, maxi, i, n;
    socklen_t   clilen;
    struct sockaddr_in  cliaddr, servaddr;
    struct pollfd       client[OPEN_MAX];
    char        buf[MAXLINE];

    /* 创建 socket */
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    /* 绑定地址到 socket */
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /* 转为监听 socket */
    if (listen(listenfd, LISTENQ)) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    client[0].fd = listenfd;
    client[0].events = POLLRDNORM;
    for (i = 1; i < OPEN_MAX; ++i) {
        client[i].fd = -1;
    }

    maxi = 0;

    for ( ; ; ) {
        nready = poll(client, maxi + 1, 1000);
        if (nready < 0) {
            perror("poll");
            exit(EXIT_FAILURE);
        } else if (nready == 0) {
            fprintf(stderr, "timeout\n");
        }

        if (client[0].revents & POLLRDNORM) {
            /* 监听 socket 上读事件 */
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
            if (connfd == -1) {
                perror("accept");
                continue;
            }
            fprintf(stderr, "accept %d\n", connfd);

            /* 从client 数组中找到一个空位 */
            for (i = 1; i < OPEN_MAX; i++) {
                if (client[i].fd < 0) {
                    client[i].fd = connfd;
                    break;
                }
            }

            if (i == OPEN_MAX) {
                fprintf(stderr, "too many clients");
                exit(EXIT_FAILURE);
            }

            client[i].events = POLLRDNORM;
            if (i > maxi) {
                maxi = i;
            }

            if (--nready <= 0) {
                continue;
            }
        }

        /* 剩余的文件描述符 */
        for (i = 1; i <= maxi; ++i) {
            if ((sockfd = client[i].fd) < 0)
                continue;
            if (client[i].revents & (POLLRDNORM | POLLERR)) {
                /* 读事件 */
                if ((n = read(sockfd, buf, MAXLINE)) < 0) {
                    if (errno == ECONNRESET) {
                        close(sockfd);
                        client[i].fd = -1;
                    } else {
                        fprintf(stderr, "read error");
                    }
                } else if (n == 0) {
                    /* 客户端关闭连接 */
                    close(sockfd);
                    client[i].fd = -1;
                } else {
                    /* 回写数据到客户端 */
                    write(sockfd, buf, n);
                }

                if (--nready <= 0) {
                    break;
                }
            }
        }
    }

    return 0;
}

参考资料

《UNP》

© 著作权归作者所有

共有 人打赏支持
for。

for。

粉丝 80
博文 47
码字总数 18257
作品 0
深圳
程序员
Linux下I/O多路复用select, poll, epoll 三种模型的Python使用

Linux下I/O多路复用select, poll, epoll 三种模型 select, poll, epoll本质上都是同步的I/O,因为它们都是在读写事件就绪后自己负责进行读写,这个读写的过程是阻塞的。 select, poll, epol...

首席贱人
2016/05/22
880
0
[Linux应用]通过sysfs在用户空间使用GPIO

ERREXIT("poll value"); / get value / ret = lseek(fd, 0, SEEK_SET); if(ret < 0) ERREXIT("lseek value"); ret = read(fd, buf, 2); buf[1] = '0'; printf("read ret = %d, value = %sn",......

zjy900507
05/11
0
0
Bittwiste - pcap 编辑工具

Bittwiste - pcap 编辑工具 It event poll2016-06-09185 阅读 工具编辑 Bittwiste的官方开源地址: bittwist.sourceforge.net 。软件提供了三个版本,分别针对FreeBSD、Linux、Windows系统。...

It event poll
2016/06/09
0
0
高性能Web服务器Nginx的配置与部署研究(8)核心模块之事件模块

本文来自:CSDN博客专栏《Nginx高性能Web服务器》 及Poechant技术博客,转载请注明出处。 一、事件模块的作用是什么? 用来设置Nginx处理链接请求。 二、相关指令 1. accept_mutex 含义:设置...

晨曦之光
2012/04/24
87
0
队列的使用

java中自带Queue 这个接口,我们查Api可以发现他所有的已知的实现类。 本文拿linkedlist举例来介绍如何使用队列 首先 队列是先进先出,也就是从队尾向里面入,从对头出 我们可以看到 offer(...

KongFanhao
2016/05/04
70
0
asyncoro 1.0 发布,Python 的并发分布式框架

asyncoro 1.0 发布,该版本改进对分布式协程、频道和监控协程的支持,并增加了一些示例来演示这些新特性。 asyncore库是python的一个标准库,它是一个异步socket的包装。我们操作网络的时候可...

oschina
2012/07/10
710
1
JAVA线程12 - 新特性:有返回值的线程

一、概述 在Java5之前,线程是没有返回值的,要实现子线程完成任务后返回值给主线程需要借助第三方转存。 在JAVA5开始,有返回值的任务可以利用Callable接口来实现。 执行Callable任务后,可...

小米米儿小
2014/03/04
0
0
阻塞队列 BlockingQueue

java.util.concurrent.BlockingQueue 接口代表了线程安全的队列。 BlockingQueue的使用 一个BlockingQueue的典型使用是一个线程不断生产对象往队列里放,另一个线程往队列里取对象进行消费。...

Kevin-air
2014/01/07
0
0
Java优先队列(PriorityQueue)示例

我们知道队列是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在队列中基于优先级处理对象。举个例子,比方说我们有一个每日交易时段生成股票报告的应用程序,需要处理大量数据并...

wx5955e325d6bfb
2017/07/04
0
0
Kafka集成Spring-AcknowledgeMessageListener接口实现

前言 因工作需要,需在系统利用Kafka监听接口,实现消息队列中,对消息的消费,首选Kafka,因为看中其超高的吞吐量。 基本概念 1 Producer: 特指消息的生产者 2 Consumer :特指消息的消费者 ...

xiaomin0322
05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

代码生成利器:IDEA 强大的 Live Templates

代码生成利器:IDEA 强大的 Live Templates

qwfys
13分钟前
0
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
16分钟前
0
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
19分钟前
0
0
日常运维--rsync同步工具

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而...

chencheng-linux
23分钟前
0
0
Java工具类—随机数

Java中常用的生成随机数有Math.random()方法及java.util.Random类.但他们生成的随机数都是伪随机的. Math.radom()方法 在jdk1.8的Math类中可以看到,Math.random()方法实际上就是调用Random类...

PrivateO2
35分钟前
0
0
关于java内存模型、并发编程的好文

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

DannyCoder
昨天
0
0
dubbo @Reference retries 重试次数 一个坑

在代码一中设置 成retries=0,也就是调用超时不用重试,结果DEBUG的时候总是重试,不是0吗,0就不用重试啊。为什么还是调用了多次呢? 结果在网上看到 这篇文章才明白 https://www.cnblogs....

奋斗的小牛
昨天
0
0
数据结构与算法3

要抓紧喽~~~~~~~放羊的孩纸回来喽 LowArray类和LowArrayApp类 程序将一个普通的Java数组封装在LowArray类中。类中的数组隐藏了起来,它是私有的,所以只有类自己的方法才能访问他。 LowArray...

沉迷于编程的小菜菜
昨天
0
0
spring boot应用测试框架介绍

一、spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit、spring test、assertj、hamcrest、mockito、jsonassert、jsonpath),但是在数...

yangjianzhou
昨天
0
0
rsync工具介绍/rsync通过ssh同步

rsync工具介绍 数据备份是必不可少,在Linux系统下数据备份的工具很多,其中重点介绍就是rsync工具,rsync不仅可以远程同步数据,还可以本地同步数据,且不会覆盖以前的数据在已经存在的数据...

Hi_Yolks
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部