多路复用技术Linux下select模型代码实现

多路复用技术Linux下select模型代码实现

头文件wrap是对socketAPI的封装 点击查看

#include "wrap.h"
#include <sys/select.h>
#include <ctype.h>
#include <fcntl.h>

int main()
{
        int lfd;	//监听文件描述符
        int cfd;	//通信文件描述符
        int nready;	//select返回值(可读事件个数)
        int maxfd;	//最大监控范围
        int n;	//读取到的字节数
        int i;	//for循环变量
        int sockfd;	//赋值为通信文件描述符,方便操作
        int flags;	//用于更改通信文件描述符为非阻塞的中间变量
        char buf[1024];	//存放读取到的数据
        fd_set readfds, tempfds;	//委托内核监控事件结构体(内部使用位操作)
		
		//创建SOCKET、设置端口复用、绑定端口、监听
        lfd = tcp4BindListen(9791, NULL, 128);
        
        maxfd = lfd;

		//初始化委托读事件结构体,并将监听文件描述符添加到结构体中
        FD_ZERO(&readfds);
        FD_SET(lfd, &readfds);

        while(1)
        {
                tempfds = readfds;
                nready = select(maxfd + 1, &tempfds, NULL, NULL, NULL);
                if(nready < 0)
                {
                        if(errno == EINTR)//被信号中断
                        {
                                continue;
                        }
                        break;
                }

                //有客户端请求连接
                if(FD_ISSET(lfd, &tempfds))
                {
                        cfd = Accept(lfd, NULL, NULL);

						//设置通信文件描述符为非阻塞
                        flags = fcntl(cfd, F_GETFL, 0);
                        flags = flags | O_NONBLOCK;
                        fcntl(cfd, F_SETFL, flags);
						
						//将通信文件描述符加入到读事件结构体中
                        FD_SET(cfd, &readfds);

						//如果文件描述符比原有文件描述符的值都大,监控范围+1
                        if(maxfd < cfd)
                        {
                                maxfd = cfd;
                        }
						
						//如果读事件-1后为0,跳出当前循环
                        if(--nready == 0)
                        {
                                continue;
                        }
                }

                //有客户端发送数据
                for(i = lfd + 1; i <= maxfd; i++)
                {
                        sockfd = i;
                        
                        //如果sockfd有可读事件
                        if(FD_ISSET(sockfd, &tempfds))
                        {
                                while(1)
                                {
                                        bzero(buf, sizeof(buf));
                                        n = Read(sockfd, buf, sizeof(buf));
										//如果客户断开连接
                                        if(n == 0)
                                        {
                                                printf("客户断开连接\n");
                                                close(sockfd);
                                                FD_CLR(sockfd, &readfds);
                                                break;
                                        }
                                        //如果数据读取完毕
                                        else if(n < 0)
                                        {
                                                printf("数据接受完毕\n");
                                                break;
                                        }
                                        //如果还有可读数据
                                        else
                                        {
                                                printf("读取数据 %s", buf);

												/*
													核心操作
												*/
                                        }
                                }
                                
                                //如果可读事件-1为0,跳出for循环
                                if(--nready == 0)
                                {
                                        break;
                                }
                        }
                }

        }
        //关闭监听文件描述符
        close(lfd);

        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值