博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poll与socket
阅读量:2433 次
发布时间:2019-05-10

本文共 4009 字,大约阅读时间需要 13 分钟。

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/

你可能感兴趣的文章
Spring的几种注入方式
查看>>
Spring自动装配
查看>>
Hibernate入门与实例
查看>>
Jython入门学习
查看>>
Hiberate基础用法实例
查看>>
Maven编译时指定JDK版本
查看>>
Hibernate单向关联N-1
查看>>
Hibernate单向关联1-1
查看>>
jQuery自定义动画
查看>>
Spring-data-redis在shiro中的实例
查看>>
GUN C中__attribute__作用
查看>>
3、系统调用之SYSCALL_DEFINE分析
查看>>
linux的signal_pending及signal
查看>>
OBJDUMP用法
查看>>
c/cplusplus通用makefile
查看>>
JavaScript-密码强度
查看>>
【SSH】1366-InCorrect string value:'\xE9\x99\x88\xE6\x96\xB0...'for column 'name' at row 1
查看>>
SpringCloud前身之微服务
查看>>
纵览全局——SSH
查看>>
纵览全局——Mybatis
查看>>