【编程】I/O复用poll函数

#include <poll.h>
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)
返回:若有就绪描述符则为其数目,若超时为0,若出错为-1
struct pollfd {
    int fd;
    short evernts;    //指定测试条件
    short revents;    //返回描述符状态
}
tcpservpoll.c
#include "unp.h"
#include <limits.h>

#define OPEN_MAX 1024 /* linux 2.x之后limits.h没有定义 OPEN_MAX 宏 */
int main(int argc, char *argv[])
{
    int i, maxi, listenfd, connfd, sockfd;
    int nready;
    ssize_t n;
    char buf[MAXLINE];
    socklen_t clilen;
    struct pollfd client[OPEN_MAX];
    struct sockaddr_in cliaddr, servaddr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
    listen(listenfd, LISTENQ);

    client[0].fd = listenfd;
    client[0].events = POLLRDNORM;/* 普通数据可读 */
    for (i = 1; i < OPEN_MAX; i++)
        client[i].fd = -1;
    maxi = 0;

    for (;;){
        printf("waitinsg poll\n");
        //nready = poll(client, maxi + 1, INFTIM);/* 等待新连接或者现有连接有数据可读 */
        nready = poll(client, maxi + 1, -1);/* 等待新连接或者现有连接有数据可读 */
        printf("nready = %d\n", nready);

        if (client[0].revents & POLLRDNORM)/* new client connection */
        {
            printf("new client connection\n");

            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (SA*)&cliaddr, &clilen);

            for(i = 1; i < OPEN_MAX; i++)
            {
                if (client[i].fd < 0)
                {

                    printf("new clients %d\n", i);
                    client[i].fd = connfd;/* save descriptor */
                    break;
                }
            }
            if (i == OPEN_MAX)
            {
                printf("too many clients\n");
                return 0;
            }
            client[i].events = POLLRDNORM;
            if (i > maxi)
            {
                maxi = i;
            }
            if (--nready <=0)
                continue;
        }

        for (i = 1; i <= maxi; i++)/* check all clients for data */
        {
            if ((sockfd = client[i].fd) < 0)
                continue;
            if (client[i].revents & (POLLRDNORM | POLLERR))
            {
                if ((n= read(sockfd, buf, MAXLINE)) < 0 )
                {
                    if (errno == ECONNRESET)
                    {
                        /* connection reset bu client */
                        close(sockfd);
                        client[i].fd = -1;
                    }
                    else
                    {
                        printf("read error\n");

                    }
                }
                else if (n == 0)
                {
                    /* connection closed by client */
                    close(sockfd);
                    client[i].fd = -1;
                }
                else
                {
                    write(sockfd, buf, n);
                }

                if (nready <= 0)
                    break;/* no more readable descriptors */
            }
        }

    }

    return 0;
}
测试客户端代码 :
#include <stdio.h>
#include <string.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>

#define SERV_IP "127.0.0.1"
#define SERV_PORT 9877
#define MAXLINE 254
#define max(a,b) (a)>=(b)?(a):(b)
int  str_cli (FILE * fp, int sockfd)
{
        int maxfdp1, stdineof;
        fd_set rset;
        char buf[MAXLINE];
        int n;

        stdineof = 0;

        for(;;)
        {
                if (stdineof == 0)
                        FD_SET(fileno(fp), &rset);
                FD_SET(sockfd, &rset);
                maxfdp1 = max(fileno(fp), sockfd) +1;

                //printf("maxfdp1 = %d\n", maxfdp1);
                select(maxfdp1, &rset, NULL, NULL, NULL);
                if (FD_ISSET(sockfd, &rset))
                {
                        if ((n = read(sockfd, buf, MAXLINE)) == 0)
                        {
                                if (stdineof == 1)
                                        return;
                                else
                                {
                                        printf("strcli:server terminated prematurely\n");
                                }
                        }
                        write(fileno(stdout),buf,n);
                }

                if (FD_ISSET(fileno(fp), &rset))
                {
                        if ((n = read(fileno(fp), buf, MAXLINE)) == 0)
                        {
                                stdineof = 1;
                                shutdown(sockfd, SHUT_WR); /*SEND FIN*/
                                FD_CLR(fileno(fp), &rset);
                                continue;
                        }
                        write(sockfd, buf, n);
                }
        }
        return 0;
}
void cli_init( int *sockfd)
{
        struct sockaddr_in servaddr;

        *sockfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);

        connect(*sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr));

        printf("connect\n");
        return;
}
int main(int argc, char *argv[])
{
        int sockfd;
        cli_init( &sockfd);
        str_cli(stdin,  sockfd);
        return 0;
}

猜你喜欢

转载自blog.csdn.net/u012335044/article/details/81777208