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

posted @ 2015-07-17 11:14  冷冰若水  阅读(549)  评论(0编辑  收藏  举报