linux网络编程 -- 并发服务器之poll

1、函数声明

poll和select类似,都是对集合里的文件描述符进行轮询

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd {
    int   fd;         /* 文件描述符 */
    short events;     /* 需要等待的事件 */
    short revents;    /* 实际返回的事件 */
};
  • fds:存放需要检测的文件描述符(一般为结构体数组)
  • nfds:要轮询的总个数
    轮询是从fds[0]开始,到fds[nfds -1]结束,后面的描述符就不管了
  • timeout:阻塞来等待文件描述符就绪的毫秒数
    <0:一直阻塞直到有文件描述符可用
    0:不阻塞,立即返回
    >0:阻塞指定的秒数再返回
  • 返回值
    成功:返回就绪的文件描述符个数(revents不为0的结构体个数)
    失败:返回-1
    0:超时,且没有任何文件描述符就绪
  • 可以轮询的事件类型
    在’events’中设置,以指示需要等待的事件
    poll返回时将出现在’revents’中,以指示文件描述符的状态
/* 可以在events中设置 ,也可能在revents中返回 */
#define POLLIN		0x001		/* 数据可读 */
#define POLLPRI		0x002		/* 高优先级数据可读 */
#define POLLOUT		0x004		/* 数据可写  */

# define POLLRDNORM	0x040		/* 正常数据可读  */
# define POLLRDBAND	0x080		/* 带优先级的数据可读  */
# define POLLWRNORM	0x100		/* 正常数据可写 */
# define POLLWRBAND	0x200		/* 带优先级的数据可写   */

/* 仅仅出现再revents中 */
#define POLLERR		0x008		/* 发生错误  */
#define POLLHUP		0x010		/* 挂起  */
#define POLLNVAL	0x020		/* 无效的轮询请求(描述符被关闭)  */

POLLIN | POLLPRI 相当于select中读事件
POLLOUT | POLLWRBAND 相当于select中写事件

2、实例

server.c

tcp_fun.h

#include "tcp_fun.h"
#include <poll.h>

#define IP "192.168.200.134"
#define PORT 2233
#define SIZE 1026//最多可容纳1024个客户端

int main() {
    int sock_fd;
    int ret,nfds;

    sock_fd = tcp_server_init(IP,PORT);
    if(sock_fd<0){
        perror("tcp_server_init");
        exit(-1);
    }

   struct pollfd fds[SIZE];
    fds[0].fd = sock_fd;
    fds[0].events = POLLIN;
    nfds = 1;

    for(int i = 1;i<SIZE;i++){
        fds[i].fd = -1;//让poll忽略
    }

    printf("listening....\n");
    while (1){
        ret = poll(fds,nfds,-1);
        if(ret<0){
            perror("poll");
            break;
        }
        else if(ret == 0){
            continue;
        }
        else{
            for (int i = 0; i < nfds; i++) {
                if(fds[i].revents & POLLIN){
                    //有新客户端连接
                    if(i == 0){
                        for(int m=0;m<SIZE;m++){
                            //查看是否还能接纳客户端
                            if(fds[m].fd == -1){
                                fds[m].fd = tcp_accept(fds[i].fd);
                                if(fds[m].fd < 0){
                                    perror("tcp_accept");
                                    fds[m].fd = -1;
                                    break;
                                }
                                fds[m].events = POLLIN;

                                if(nfds < m+1){
                                //如果轮询数小于描述符的个数
                                    nfds++;
                                }
                                break;
                            }
                            if(m==SIZE-1){
                                //客户端过多,先连接再关闭
                                int fd = tcp_accept(fds[i].fd);
                                close(fd);
                                printf("too many clients\n");
                            }
                        }
                    }
                    else{
                        //有客户端发消息
                        ret = tcp_server_chat(fds[i].fd);
                        if(ret <=0){
                           // 客户端退出或出错
                            close(fds[i].fd);
                            fds[i].fd = -1;
                            if(nfds == i+1){
                                nfds--;
                            }
                        }
                    }
                } else if(fds[i].revents & POLLERR){
                    //出错处理
                    close(fds[i].fd);
                    fds[i].fd = -1;
                    if(nfds == i+1){
                        nfds--;
                    }
                }
            }
        }
    }
    return 0;
}

client.c

#include "tcp_fun.h"

#define IP "192.168.200.134"
#define PORT 2233

int main(int argc ,char **argv) {
    int fd = tcp_client_init(IP, PORT);
    if(fd < 0){
        perror("tcp_client_init");
    }

    tcp_client_chat(fd);
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值