poll与socket

poll函数与select类似,最显著的区别是提供fd的方式不一样。
要让poll监控文件描述符的话,需要提供一个struct pollfd的数组。
struct pollfd的内容如下
/* Data structure describing a polling request.  */
struct pollfd
{
    int fd;         /* File descriptor to poll.  */
    short int events;       /* Types of events poller cares about.  */
    short int revents;      /* Types of events that actually occurred.  */
};
其中fd是文件描述符,events是需要监控的事件,revents是实际发生的事件。
当监控的事件时,poll函数会修改struct pollfd数组里每个pollfd.revents。
events和revents可选的值如下
/* Event types that can be polled for.  These bits may be set in `events'
   to indicate the interesting event types; they will appear in `revents'
   to indicate the status of the file descriptor.  */
#define POLLIN      0x001       /* There is data to read.  */
#define POLLPRI     0x002       /* There is urgent data to read.  */
#define POLLOUT     0x004       /* Writing now will not block.  */

#if defined __USE_XOPEN || defined __USE_XOPEN2K8
/* These values are defined in XPG4.2.  */
# define POLLRDNORM 0x040       /* Normal data may be read.  */
# define POLLRDBAND 0x080       /* Priority data may be read.  */
# define POLLWRNORM 0x100       /* Writing now will not block.  */
# define POLLWRBAND 0x200       /* Priority data may be written.  */
#endif

#ifdef __USE_GNU
/* These are extensions for Linux.  */
# define POLLMSG    0x400
# define POLLREMOVE 0x1000
# define POLLRDHUP  0x2000
#endif

/* Event types always implicitly polled for.  These bits need not be set in
   `events', but they will appear in `revents' to indicate the status of
   the file descriptor.  */
#define POLLERR     0x008       /* Error condition.  */
#define POLLHUP     0x010       /* Hung up.  */
#define POLLNVAL    0x020       /* Invalid polling request.  */



下面这个例子监听4444端口,结合poll来管理多个网络连接。
客户端用普通的telnet就可以
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int do_listen(char* ip, int port, int backlog)
{
    int fd = 0;
    if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
    {
        puts(strerror(errno));
        exit(errno);
    }

    int opt = 1;
    setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &servaddr.sin_addr);
    servaddr.sin_port = htons(port);

    if(bind(fd, (struct sockaddr*)&servaddr, sizeof(servaddr) ) < 0)
    {
        puts(strerror(errno));
        exit(errno);
    }
    listen(fd, backlog);
    return fd;
}

int do_poll(int sock, int maxfd)
{
    struct sockaddr_in clientaddr;
    socklen_t socklen = sizeof(clientaddr);
    struct pollfd fds[maxfd];
    int max = 2;
    int ok = 0;

    fds[0].fd = sock;
    fds[0].events = POLLIN;

    int i = 0;
    for(; ++i < maxfd; fds[i].fd=-1);

    int cnt = 0;
    char buf[BUFSIZ];
    char hello[10] = "hello";
    int conn = 0;
    int added = 0;
    while(1)
    {
        int ok = poll(fds, max, -1);
        printf("poll %d\n", ok);
        if(ok < 0)
        {
            printf("poll error: %s\n", strerror(errno));
            exit(errno);
        }
        if(fds[0].revents & POLLIN == POLLIN)
        {
            if((conn = accept(sock, (struct sockaddr*)&clientaddr, &socklen)) < 0)
            {
                if(errno == EINTR) continue;
                printf("accept error: %s\n", strerror(errno));
                exit(errno);
            }
            for(i=1; i<maxfd; i++)
            {
                if(fds[i].fd < 0)
                {
                    fds[i].fd = conn;
                    fds[i].events = POLLIN;
                    added = 1;
                    if(i>=max) max = i+1;
                    break;
                }
            }
            if(added == 0)
            {
                printf("drop connect: %s:%d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
            }
            added = 0;
            printf("accept: %d,  %s:%d\n", conn, inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);

        }
        else
        {
            // check all fd
            printf("from client...\n");
            for(i=1; i<maxfd; i++)
            {
                if(fds[i].fd < 0) continue;
                if(fds[i].revents & POLLIN)
                {
                    cnt = read(fds[i].fd, buf, BUFSIZ);
                    if(cnt == 0 || *buf == EOF)
                    {
                        close(fds[i].fd);
                        fds[i].fd = -1;
                        printf("client exit\n");
                        continue;
                    }
                    buf[cnt] = '\0';
                    printf("from client: %s", buf);
                    write(fds[i].fd, hello, 5);
                    write(fds[i].fd, buf, cnt);
                }
            }
        }

    }

    return 0;
}

int main()
{
    int sock = do_listen("0.0.0.0", 4444, 100);
    do_poll(sock, 1024);

    close(sock);
    return 0;
}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2075383/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26239116/viewspace-2075383/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值