多路复用的概念: 在我们linux函数接口里面有很多函数都是带阻塞功能的,例如是:read/write/accept…
阻塞函数,这些函数都是当到达某个条件的时候才会阻塞,例如read函数,当网络没有数据的时候回读会阻塞
例如:write写函数当管道写满的时候他又会阻塞。。。。。
遇到这里阻塞的问题我们之前都是,开线程去处理他,这样会造成资源的浪费。
多路复用的接口函数:
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
//多路复用的设置函数
int select(int nfds, // 所有监控的文件描述符中最大的那一个加1
fd_set *readfds,// 需要监视的读集合,所有要读的文件文件描述符的集合
fd_set *writefds,// 需要监视的写集合,所有要的写文件文件描述符的集合
fd_set *exceptfds,//其他要向我们通知的文件描述符 ->一般为NULL
struct timeval timeout*);//超时设置. 设置他监视的 时长
//时间结构体
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
返回值:成功:返回文件描述 (返回 1)
超时:返回0
失败:返回-1
void FD_CLR(int fd, fd_set *set);//将FD从fd_set 删除
int FD_ISSET(int fd, fd_set *set); //判断fd是否在fd_set集合中
void FD_SET(int fd, fd_set *set);// 将FD加到fd_set集合里面中
void FD_ZERO(fd_set *set); //清空fd_set集合
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main()
{
//1.创建TCP通信对象
int socketfd=socket(AF_INET,SOCK_STREAM,0);
if(socketfd < 0)
{
perror("creat sock fail\n");
return -1;
}
//2.链接服务器
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //指定网络协议为 IPV4
seraddr.sin_port = htons(12580); //取值范围 最大值65535 16位的整形 1024以后
seraddr.sin_addr.s_addr = inet_addr("10.8.6.108"); //自动检测IP地址
int ret=connect(socketfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret != 0)
{
perror("connect fail\n");
return -1;
}
else
{
printf("connect ok\n");
}
//开启集合的监视
//定义一个文件描述符集合
fd_set fds;
//定义一个时间结构体
struct timeval time;
//循环监视文件描述符集合
while(1)
{
//清空文件描述符集合
FD_ZERO(&fds);
//把标准输入设备加入到集合中
FD_SET(0,&fds);
//把网络通信文件描述符加入到集合中
FD_SET(socketfd,&fds);
//设置监视的时长
time.tv_sec = 5;
time.tv_usec = 0;
int ret=select(socketfd+1,&fds,NULL,NULL,&time);
if(ret < 0)//错误
{
perror("select fail:");
return -1;
}
else if(ret == 0) //超时
{
printf("timeout\n");
}
else if(ret > 0) //有活跃的
{
printf("ret=%d\n",ret);
//判断是否 标准输入设备活跃 假设是则发送数据
if(FD_ISSET(0,&fds))
{
char buf[1024]={0};
read(0,buf,1024);
//发送到网络中
write(socketfd,buf,strlen(buf));
}
//判断是否有数据录入
if(FD_ISSET(socketfd,&fds))
{
char buf[1024]={0};
read(socketfd,buf,1024);
printf("getdate=%s\n",buf);
}
}
}
}