网络编程之——多路IO转接(poll模型)

15 篇文章 0 订阅
12 篇文章 0 订阅

poll函数原型

struct pollfd {
	int   fd;         /* file descriptor */
	short events;     /* requested events */
	short revents;    /* returned events */
};
//fds  监听数组
//nfds 监听数组的实际个数
//timeout -1 无限超时
//		   0 立即返回
//		  >0 超时返回     
//返回值   >0结构体中revents域不为0的文件描述符个数
//		   0没有任何事件发生
//		  -1错误    
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

示例

#include "wrap.h"
#include "stdio.h"
#include "stdlib.h"
#include "netinet/ip.h"
#include "sys/poll.h"
#include "unistd.h"
#include "strings.h"
#include "ctype.h"
#include "arpa/inet.h"

#define PORT 8888
#define OPEN_MAX    1000

void server_select()
{
    int lfd = 0;
    int cfd = 0;
    int lNum = 0,i,n;

    struct sockaddr_in serv_addr,clit_addr;
    socklen_t clit_addr_len;
    char buf[BUFSIZ];
    char clit_ip[1024];
    bzero(&serv_addr,sizeof(serv_addr));
    bzero(&clit_addr,sizeof(clit_addr));
    bzero(buf,sizeof(char)*BUFSIZ);
    bzero(clit_ip,sizeof(char)*1024);
    clit_addr_len = sizeof(clit_addr);

    //设置服务器地址和端口
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    //创建socket
    lfd = Socket(AF_INET,SOCK_STREAM,0);

    int opt = 1;//设置端口复用
    Setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));

    Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));//绑定服务器地址 端口
    Listen(lfd,128);

    struct  pollfd pfds[OPEN_MAX];
    //初始化客户连接描述符
    for (i = 1;i < OPEN_MAX;i++)
        pfds[i].fd = -1;
    pfds[0].fd = lfd;
    pfds[0].events = POLLIN;
    pfds[0].revents = 0;
    int maxi=0;
    while (1)
    {
        lNum = poll(pfds,maxi+1,0);
        if (lNum<0)
        {
            sys_err("poll error");
        }else
        {
            if(pfds[0].revents & POLLIN)
            {
                cfd = Accept(lfd,(struct sockaddr*)&clit_addr,&clit_addr_len);//连接   非阻塞

                printf("client ip:%s,port:%d\n",
                    inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,clit_ip,1024),
                    ntohs(clit_addr.sin_port));

                //将新的连接描述符添加到数组中
                for (i = 1;i < OPEN_MAX;i++)
                {
                    if (pfds[i].fd < 0)
                    {
                        pfds[i].fd = cfd;
                        break;
                    }
                }
                if (i == OPEN_MAX)
                {
                    fprintf(stderr,"too many clients.\n");
                    exit(1);
                }
                //将新的描述符添加到读描述符集合中
                pfds[i].events = POLLIN;
                //记录客户连接套接字的个数
                maxi = (i > maxi ? i : maxi);
            }
            
            if(lNum == 1)
            {
                continue;
            }           
        }

        for(i=1;i<=maxi;++i)//遍历处理读集合中的描述符请求
        {
            if (pfds[i].fd < 0)
                continue;
            //测试客户描述符是否准备好
            if (pfds[i].revents & POLLIN)
            {
                n = read(pfds[i].fd,buf,sizeof(buf));
                if(n == 0)
                {
                    Close(pfds[i].fd);
                    printf("client %d exit\n",ntohs(clit_addr.sin_port));
                    continue;
                }
                write(STDOUT_FILENO,buf,n);
                for(int j=0;j<n;++j)
                {
                    buf[j] = toupper(buf[j]);
                }
                write(pfds[i].fd,buf,n);
            }           
        }

    }

    Close(lfd);
    Close(cfd);
}

int main(int args,char *argc[])
{
    server_select();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值