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));
            }
        }

    }
}
时间: 2024-10-10 10:13:16

linux C poll 函数使用的相关文章

Linux下poll函数实现多用户聊天

Client: #define _GNU_SOURCE 1 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include<arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <string.h> #incl

Linux网络编程——I/O复用之poll函数

一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大,同时每次调用 select() 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大. 2.单个进程能够监视的文件描述符的数量存在最大限制,在 Linux 上一般为 1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效

linux poll函数

poll函数与select函数差不多 函数原型: #include <poll.h> int poll(struct pollfd fd[], nfds_t nfds, int timeout); struct pollfd的结构如下: struct pollfd{ int fd: // 文件描述符 short event:// 请求的事件 short revent:// 返回的事件 } 每个pollfd结构体指定了一个被监视的文件描述符.第一个参数是一个数组,即poll函数可以监视多个文件描

linux 下 poll 编程

poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪.如果有就返回就绪文件描述符的个数将.poll 函数如下: #include <poll.h> int poll(struct pollfd *fdarray, unsigned long nfds, int timeout) 第一个参数指向结构数组第一个元素的指针,每个数组都是一个 pollfd 结构iouyonghu制定额是某个给定描述符的条件. struct pollfd { int fd; short eve

Linux中select函数

转载自:http://blog.163.com/henry_hlh/blog/static/17039507420124211841298/ Unix中的函数select和poll用来,支持Unix中I/O复用的功能,在Unix中I/O模型可以分为以一几种: (1)阻塞I/O (2)非阻塞I/O (3)I/O复用(select和poll) (4)信号驱动I/O(SIGIO) (5)异步I/O 其中,现在比较流行的I/O模型是阻塞I/O模型.阻塞I/O是当应用程序和内核交换数据时,由于内核还没有准

Linux网络编程函数

转自:http://blog.csdn.net/hrbeuwhw/article/details/8050911 1.字节序函数 #include<netinet.h> uint16_t htons(uint16_t host16bitvalue); uint32_t htonl(uint32_t host32bitvalue); 返回:网络字节序值 uint16_t ntohs(uint16_t net16bitvalue); uint32_t ntohl(uint32_t net32bit

Linux之poll与select20160619

使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问,这两个系统调用最终又会引发设备驱动中的poll()函数被执行 如果当前不可读(先调用驱动.poll确定是否可读,然后继续do_poll),那么在sys_poll->do_poll中当前进程就会睡眠在等待队列上,这个等待队列是由驱动程序提供的(就是poll_wait中传入的那个).当可读的时候,驱动程序可能有一部分代码运行了(比如驱动的中断服务 程序),那么在这部分代码中,就会唤醒等待队列上

对于linux下system()函数的深度理解(整理)

对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54) 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定?

linux中fork()函数详解[zz]

转载自:http://www.cnblogs.com/york-hust/archive/2012/11/23/2784534.html 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事. 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间.然后把原来的进程的所有值都复制到新的新进程中,只有