多路IO复用之poll

与select相比,poll能突破1024个文件描述符的限制.

server_poll.c

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <arpa/inet.h>

#include <ctype.h>

#include <errno.h>

#include <poll.h>

#define MAXLINE 80

#define SERV_PORT 6666

#define OPEN_MAX 1024

int main()

{

    //1.创建socket

    struct sockaddr_in serv_addr, clnt_addr;

    int lfd, cfd, sockfd;

    socklen_t clnt_size;

    int i, j, n, nready, maxi;

    struct pollfd clients[OPEN_MAX];

    lfd = socket(AF_INET, SOCK_STREAM, 0);

    int opt = 1;

    setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    serv_addr.sin_port = htons(SERV_PORT);

    bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    listen(lfd, 128);

    clients[0].fd = lfd;

    clients[0].events = POLLIN; //监听读事件

    for(i = 1; i < OPEN_MAX; i++){

        clients[i].fd = -1;

    }

    maxi = 0;

    clnt_size = sizeof(clnt_addr);

    char readBuf[1024];

    while(1){

        nready = poll(clients, maxi+1, -1);

        printf("nready = %d\n", nready);

        //有新的连接

        if(clients[0].revents & POLLIN){

            printf("有新的连接...\n");

            cfd = accept(lfd, (struct sockaddr*)&clnt_addr, &clnt_size);

            printf("cfd = %d\n", cfd);

            for(i = 1; i < OPEN_MAX; i++){

                if(clients[i].fd < 0){

                    clients[i].fd = cfd;

                    clients[i].events = POLLIN;

                    break;

                }

            }

        if(i == OPEN_MAX){

           printf("too many connection\n");

           exit(1);

         }

        maxi = (i > maxi ? i : maxi);

        if(--nready <= 0){

            continue;

        }

    }

    //已建立的连接发送数据

    printf("maxi = %d\n", maxi);

    for(i = 1; i <= maxi; i++){

        if((sockfd = clients[i].fd) < 0){

            printf("sockfd 小于0\n");

            continue;

        }

        if(clients[i].revents & POLLIN){

        if((n = read(sockfd, readBuf, sizeof(readBuf))) < 0){

            if(errno == ECONNRESET){

                printf("客户端 %d 重置连接\n", i+1);

                close(sockfd);

                clients[i].fd = -1;

            }else{

                perror("read error");

                exit(1);

            }

        }else if(n == 0){ //客户端关闭连接

            printf("客户端 %d 关闭连接\n", i+1);

            close(sockfd);

            clients[i].fd = -1;

        }else if(n > 0){ //有数据

            for(j = 0; j < n; j++){

                readBuf[j] = toupper(readBuf[j]);

            }

        write(sockfd, readBuf, n);

        write(STDOUT_FILENO, readBuf, n); //写到标准输出

    }

}

    if(--nready <= 0){

        break;

    }

    }

}

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、基本知识 poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根...
    Daniel521阅读 3,085评论 0 0
  • 多路IO转接服务器也叫做多任务IO服务器。该类服务器实现的主旨思想是,不再由应用程序自己监视客户端连接,取而代之由...
    ezjuhnz阅读 3,355评论 0 0
  • epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量...
    ezjuhnz阅读 3,514评论 0 0
  • 1、基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用...
    Daniel521阅读 3,196评论 0 0
  • 1、基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和po...
    Daniel521阅读 3,998评论 0 1