linux C poll 函数使用

Posted Just_Boy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux C poll 函数使用相关的知识,希望对你有一定的参考价值。

在学习linux 并发非阻塞服务器时候。看到有使用poll 函数的方式。初步理解并编写程序进行了测试。

服务器:

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include  <poll.h>

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAX_LINK 10

int main()
{
    struct sockaddr_in server_addr,client_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(6888);
    
    socklen_t socklen = sizeof(struct sockaddr_in);
    
    int ser_fd,con_fd;
    ser_fd=socket(AF_INET, SOCK_STREAM, 0);

    if(bind(ser_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)) == -1) {
        perror("bind error");
        exit(-1);
    }

    if (listen(ser_fd,10) < 0) {
        perror("listen error");
        return -1;
    }
    
    struct pollfd fds[MAX_LINK];
    fds[0].fd=ser_fd;
    fds[0].events=POLLRDNORM;
    int i=1;
    for(;i<MAX_LINK;i++){
        fds[i].fd=-1;
        fds[i].events=POLLRDNORM;    
    }
    
    int ready_n;
    
    int link_count=1;
    
    char buffer[1024];
    
    while(1){
        ready_n=poll(fds,link_count,-1);
        if(ready_n==-1){
            printf("poll error \n");
            return 0;
        }
        if(fds[0].revents & POLLRDNORM){
            int cli=accept(ser_fd, (struct sockaddr*) &client_addr, &socklen);
            for(i=1;i<MAX_LINK;i++){
                if(fds[i].fd<0){
                    fds[i].fd=cli;
                    printf("new connect : %d \t",i);
                    printf("%d\n",link_count);
                    break;
                }
            }
            link_count++;
            ready_n--;
        }
        for(i=1;i<MAX_LINK && ready_n>0;i++){
            if(fds[i].fd >0){
                if(fds[i].revents & POLLRDNORM){
                    int n=recv(fds[i].fd,buffer,1024,0);
                    if(n==0){
                        fds[i].fd=-1;
                        link_count--;
                        
                    }else if(n>0){
                        send(fds[i].fd,buffer,n,0);
                    }
                    ready_n--;
                }
            }
        
        }
            
    
    }
    

    return 0;
}

客户端:

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <sys/select.h>       /* select function*/

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 10240
#define max(a,b)    ((a) > (b) ? (a) : (b))
//typedef struct sockaddr  SA;

void handle(int sockfd);

int main(int argc, char **argv)
{
    char * servInetAddr = "127.0.0.1";
    int servPort = 6888;
    char buf[MAXLINE];
    int connfd;
    struct sockaddr_in servaddr;
    
    if (argc == 2) {
        servInetAddr = argv[1];
    }
    if (argc == 3) {
        servInetAddr = argv[1];
        servPort = atoi(argv[2]);
    }
    if (argc > 3) {
        printf("usage: selectechoclient <IPaddress> <Port>\n");
        return -1;
    }

    connfd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(servPort);
    inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr);
    
    if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("connect error");
        return -1;
    }
    printf("welcome to selectechoclient\n");
    handle(connfd);     /* do it all */
    close(connfd);
    printf("exit\n");
    exit(0);
}


void handle(int connfd)
{
    FILE* fp = stdin;
    char sendline[MAXLINE], recvline[MAXLINE];
    fd_set rset;
    FD_ZERO(&rset);
    int maxfds = max(fileno(fp), connfd) + 1;
    int nread;
    for (;;) {
        FD_SET(fileno(fp), &rset);
        FD_SET(connfd, &rset);

        if (select(maxfds, &rset, NULL, NULL, NULL) == -1) {
            perror("select error");
            continue;
        }

        if (FD_ISSET(connfd, &rset)) {
            //接收到服务器响应
            nread = read(connfd, recvline, MAXLINE);
            if (nread == 0) {
                printf("server close the connection\n");
                break;
            } 
            else if (nread == -1) {
                perror("read error");
                break;    
            }
            else {
                //server response
                write(STDOUT_FILENO, recvline, nread);    
            }  
        }

        if (FD_ISSET(fileno(fp), &rset)) {
            //标准输入可读
            if (fgets(sendline, MAXLINE, fp) == NULL) {
                //eof exit
                break;   
            } 
            else {
                write(connfd, sendline, strlen(sendline));  
            }
        }

    } 
}

 

以上是关于linux C poll 函数使用的主要内容,如果未能解决你的问题,请参考以下文章

Linux C - poll示例

linux驱动之poll操作

linux poll函数

Linux-应用程序中的poll机制

Linux内核poll内部实现

linux poll机制使用