• 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

  • 相关阅读:
    nginx查看配置文件nginx.conf路径
    http://127.0.0.1/thinkphp5/public/index/teacher/delete/id/1.html 这样的URL下,页面收不到get参数
    thinkphp5访问报错 ...with message 'mkdir(): Permission denied' in... 或...failed to open stream: Permission denied' in...
    thinkphp报错No input file specified. (对于隐藏url中的index.php 是如何做到的?)
    收藏网址
    jquery 和 原生js 获取<select><option></option></select>标签的值和文本
    Macbook下MySQL卸载方法
    提示错误 Call to undefined function imagepng() in …
    Mac 安装phpmyadmin提示无法登陆 mysql服务器解决办法
    php把一个字符串分割成字符数组(可以用参数指定数组每个元素字符的长度)
  • 原文地址:https://www.cnblogs.com/lit10050528/p/4653864.html
Copyright © 2020-2023  润新知