zoukankan      html  css  js  c++  java
  • linux poll 学习

    一、poll介绍

     函数原型:

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

    struct pollfd定义:

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

    fd:文件描述符

    events:关心的事件,输入参数

    revents:产生的事件,输出参数

    事件类型:

    POLLIN    普通或优先级带数据可读
    POLLRDNORM    普通数据可读
    POLLRDBAND    优先级带数据可读
    POLLPRI    高优先级数据可读
    POLLOUT    普通数据可写
    POLLWRNORM    普通数据可写
    POLLWRBAND    优先级带数据可写
    POLLERR    发生错误
    POLLHUP    发生挂起
    POLLNVAL    描述字不是一个打开的文件

    关于poll的具体用法,请见下面示例。

    二、poll使用

    示例1:回显服务器

    /*******************************************************************************
    * File Name        : poll.cpp
    * Author        : zjw
    * Email            : emp3XzA3MjJAMTYzLmNvbQo= (base64 encode)
    * Create Time    : 2015年07月17日 星期五 09时42分11秒
    *******************************************************************************/
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <poll.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cerrno>
    #include <cstring>
    using namespace std;
    
    const int SERVER_PORT = 8080;
    const int EVENT_SIZE = 1024;
    const int RECV_SIZE = 1024;
    const int SEND_SIZE = 1040;
    
    int main(int argc, char **argv)
    {
        int server = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in addrServer;
        bzero(&addrServer, sizeof(addrServer));
        addrServer.sin_family = AF_INET;
        addrServer.sin_port = htons(SERVER_PORT);
        addrServer.sin_addr.s_addr = INADDR_ANY;
    
        if (bind(server, (struct sockaddr*)&addrServer, sizeof(addrServer)))
        {
            perror("bind failed,");
            return -1;
        }
    
        listen(server, 10);
        cout << "listening on port:" << SERVER_PORT << " ..." << endl;
    
        struct pollfd fds[EVENT_SIZE] = {{0, 0, 0}};
        fds[server].fd = server;
        fds[server].events = POLLIN;
    
        int ret = 0;
        char recvBuf[RECV_SIZE + 1];
        char sendBuf[SEND_SIZE + 1];
        while (1)
        {
            if ((ret = poll(fds, EVENT_SIZE, 0)) < 0)
            {
                perror("poll failed,");
                return -1;
            }
    
            for (int i = 0; i < EVENT_SIZE; i++)
            {
                if (fds[i].fd == 0)
                {
                    continue;
                }
    
                if (fds[i].fd == server && (fds[i].revents & POLLIN))
                { // accept a new client
                    struct sockaddr_in addrClient;
                    socklen_t len = sizeof(addrClient);
                    int client = accept(server, (struct sockaddr*)&addrClient, &len);
                    if (client == -1)
                    {
                        perror("accept failed,");
                        return -1;
                    }
                    else
                    {
                        cout << "accep an new client " << client << ", ip:" << inet_ntoa(addrClient.sin_addr) << endl;
                        fds[client].fd = client;
                        fds[client].events = POLLIN;
                    }
                }
                else if (fds[i].revents & POLLIN)
                { // read event
                    memset(recvBuf, 0, RECV_SIZE + 1);
                    if ((ret = recv(fds[i].fd, recvBuf, RECV_SIZE, 0)) < 0)
                    {
                        perror("recv failed,");
                        return -1;
                    }
                    else if (ret == 0)
                    { // client close
                        close(fds[i].fd);
                        fds[i].fd = 0;
                    }
                    else
                    { // recv data
                        cout << "client " << fds[i].fd << " said:" << recvBuf << endl;    
                        memset(sendBuf, 0, SEND_SIZE + 1);
                        sprintf(sendBuf, "You said:%s", recvBuf);
                        if ((ret = send(fds[i].fd, sendBuf, SEND_SIZE, 0)) < 0)
                        {
                            perror("send failed,");
                            return -1;
                        }
                    }
                }
                else
                { // write event
                    
                }
            }
        }
        close(server);
    
        return 0;
    }

    Makefile:

    echo: poll.cpp
        g++ -g -o $@ $<
    
    clean:
        rm -rf echo

    运行结果:

    服务器端:

    客户端1:

    客户端2:

    三、参考

    http://www.360doc.com/content/12/0821/10/7775902_231465100.shtml

    http://blog.chinaunix.net/uid-23842323-id-2656589.html

  • 相关阅读:
    .NET微信网页开发之JS-SDK使用步骤和配置信息timestamp(时间戳),nonceStr(随机串),signature(签名),access_token(接口调用凭据)的生成获取讲解
    .NET项目中NLog的配置与使用
    ASP.NET MVC中使用jQuery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径
    Linux CentOS上安装 MySQL 8.0.16
    微信小程序开发之多图片上传+.NET WebAPI后端服务保存图片资源
    MySQL 查询重复数据,删除重复数据保留id最小的一条作为唯一数据
    .NET轻松实现支付宝服务窗网页授权并获取用户相关信息
    .NET微信网页开发之通过UnionID机制,解决用户在不同公众号,或在公众号、移动应用之间帐号统一问题
    Navicat远程连接MySQL 提示1045
    Vs Code推荐安装插件
  • 原文地址:https://www.cnblogs.com/lit10050528/p/4653864.html
Copyright © 2011-2022 走看看