【网络编程】poll函数

简介: 【网络编程】poll函数

poll和select的区别不大,主要是poll没有连接数限制,因为它用的链表实现

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
   
    int   fd;         //要监控的文件描述符,如果fd为-1, 表示内核不再监控
    short events;     //输入参数, 表示告诉内核要监控的事件, 读事件, 写事件, 异常事件
    short revents;    //输出参数, 表示内核告诉应用程序有哪些文件描述符有事件发生
};
events/revents:
           POLLIN:可读事件
           POLLOUT: 可写事件
           POLLERR: 异常事件
nfds: 告诉内核监控的范围, 具体是: 数组下标的最大值+1 
timeout: 
    =0: 不阻塞, 立刻返回
    -1: 表示一直阻塞, 直到有事件发生
    >0: 表示阻塞时长, 在时长范围内若有事件发生会立刻返回;
        如果超过了时长也会立刻返回
函数返回值:
    >0: 发生变化的文件描述符的个数
    =0: 没有文件描述符发生变化
    -1: 表示异常

使用poll来监控多个文件描述符进行客户端通信

代码:

#include "socketwrap.h"
#include <arpa/inet.h>
#include <poll.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>

#define POLLLEN 1024

int main()
{
   
    int sfd = Socket(AF_INET, SOCK_STREAM, 0);

    // 设置端口复用
    int opt = 1;
    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

    struct sockaddr_in soaddr;
    bzero(&soaddr, sizeof(soaddr));

    soaddr.sin_family = AF_INET;
    soaddr.sin_port = htons(9999);
    soaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    Bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr));

    // 监听-listen
    Listen(sfd, 128);

    struct pollfd connfd[POLLLEN];

    int maxfd;  // 当前需要监听的最大的文件描述符
    int nready; // 返回的需要处理的个数
    int cfd;    // 通信描述符
    int i, maxi = 0;

    struct sockaddr_in clientsocket;
    socklen_t clilen;
    char buff[64]; // 通信数据

    // 初始化有效的文件描述符数组
    for (int i = 0; i < POLLLEN; i++)
    {
   
        bzero(&connfd[i], sizeof(connfd[i]));
        connfd[i].fd = -1;
    }

    maxfd = sfd;
    connfd[0].fd = sfd;
    connfd[0].events = POLLIN;

    while (1)
    {
   
        clilen = sizeof(clientsocket);
        bzero(&clientsocket, clilen);

        nready = poll(connfd, maxfd + 1, -1);

        if (nready < 0)
        {
   
            if (errno == EINTR) // 被信号中断
            {
   
                continue;
            }
            perror("poll error");
            break;
        }

        if (nready > 0)
        {
   
            if (connfd[0].revents == POLLIN)
            {
   
                // 有连接到来
                cfd = Accept(sfd, (struct sockaddr *)&clientsocket, &clilen);

                for (i = 0; i < POLLLEN; i++)
                {
   
                    if (connfd[i].fd == -1)
                    {
   
                        connfd[i].events = POLLIN;
                        connfd[i].fd = cfd;
                        maxi = i;
                        if (maxfd < cfd)
                        {
   
                            maxfd = cfd;
                        }
                        // 打印客户端的IP和PORT
                        char sIP[16];
                        memset(sIP, 0x00, sizeof(sIP));
                        printf("client [%s:%d] connect\n", inet_ntop(AF_INET, &clientsocket.sin_addr.s_addr, sIP, sizeof(sIP)), htons(clientsocket.sin_port));
                        break;
                    }
                }
                if (i == POLLLEN)
                {
   
                    close(cfd);
                    printf("connect too much, server busy\n");
                    continue;
                }

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

            for (i = 1; i <= maxi; i++)
            {
   
                if (connfd[i].fd == -1)
                {
   
                    continue;
                }
                if (connfd[i].revents == POLLIN)
                {
   
                    // 有数据发送过来
                    int n;
                    int sockfd = connfd[i].fd;
                    memset(buff, 0x00, sizeof(buff));
                    n = Read(sockfd, buff, sizeof(buff));
                    if (n < 0)
                    {
   
                        perror("read over");
                        close(sockfd);
                        bzero(&connfd[i], sizeof(bzero));
                        connfd[i].fd = -1; // 将connfd[i]置为-1,表示该位置可用
                    }
                    else if (n == 0)
                    {
   
                        // printf("client is closed\n");
                        close(sockfd);
                        bzero(&connfd[i], sizeof(bzero));
                        connfd[i].fd = -1; // 将connfd[i]置为-1,表示该位置可用
                    }
                    else
                    {
   
                        printf("[%d]:[%s]\n", n, buff);
                        for (i = 0; i < n; i++)
                        {
   
                            buff[i] = toupper(buff[i]);
                        }

                        Write(sockfd, buff, n);
                    }

                    if (--nready <= 0)
                    {
   
                        break; // 注意这里是break,而不是continue, 应该是从最外层的while继续循环
                    }
                }
            }
        }
    }

    close(sfd);

    return 0;
}
目录
相关文章
|
19天前
|
机器学习/深度学习 算法
神经网络中激活函数的重要性
【8月更文挑战第23天】
11 0
|
23天前
|
监控
【网络编程】select函数
【网络编程】select函数
31 0
|
23天前
|
机器学习/深度学习 Shell 计算机视觉
一文搞懂 卷积神经网络 卷积算子应用举例 池化 激活函数
这篇文章通过案例详细解释了卷积神经网络中的卷积算子应用、池化操作和激活函数,包括如何使用卷积算子进行边缘检测和图像模糊,以及ReLU激活函数如何解决梯度消失问题。
|
2月前
|
机器学习/深度学习
神经网络可能不再需要激活函数?Layer Normalization也具有非线性表达!
【7月更文挑战第14天】研究表明,层归一化(LayerNorm)可能具备非线性表达能力,挑战了神经网络对激活函数的依赖。在LN-Net结构中,仅使用线性层与LayerNorm就能实现复杂分类,其VC维度下界证明了非线性表达。尽管如此,是否能完全替代激活函数及如何有效利用这一特性仍需更多研究。[arXiv:2406.01255]
37 5
|
2月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于负相关误差函数的4集成BP神经网络matlab建模与仿真
**算法预览:** 图像显示无水印的2022a版MATLAB运行结果 **软件版本:** MATLAB 2022a **核心代码片段:** 省略展示 **理论概述:** NCL集成BP网络利用负相关提升泛化,结合多个弱模型减少错误关联。通过λ参数控制模型间负相关程度,λ&gt;0增强集成效果,提高预测准确性和系统稳健性。
|
2月前
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。
|
2天前
|
安全 网络安全 数据安全/隐私保护
数字堡垒之下:网络安全漏洞与信息安全的守护之路
在数字化浪潮中,网络安全成为保护个人隐私和企业数据的关键防线。本文将探讨网络漏洞的发现与利用,加密技术在信息保护中的作用,以及提升安全意识的重要性。我们将从基础概念出发,通过案例分析,深入了解网络攻防的动态平衡,并分享实用的安全策略,旨在为读者提供一条清晰的信息安全守护路径。
10 2
|
2天前
|
安全 算法 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第8天】本文将探讨网络安全与信息安全的重要性,以及如何保护个人和组织的信息资产。我们将讨论网络安全漏洞、加密技术、安全意识等方面的内容,并提供一些实用的建议和技巧来帮助读者提高他们的网络安全水平。无论你是个人用户还是企业管理员,都可以从本文中获得有关如何保护自己免受网络威胁的有用信息。
178 89
|
1天前
|
存储 监控 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第9天】在数字化时代,网络安全和信息安全已成为我们生活的重要组成部分。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的知识和技巧来保护您的个人信息和数据安全。我们将通过深入浅出的方式,帮助您了解网络威胁的来源,如何利用加密技术保护自己的数据,以及如何提高自己的安全意识。无论您是个人用户还是企业,这些知识都将对您有所帮助。让我们一起来学习如何保护自己的网络安全吧!
|
1天前
|
安全 网络协议 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第9天】在数字时代,网络安全和信息安全成为了全球关注的焦点。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的内容,帮助读者更好地了解这些概念,并提高自身的网络安全意识和技能。