IO多路复用机制
- 使用I/O多路复用技术。其基本思想是:
- 先构造一张有关描述符的表,然后调用一个函数。
- 当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。
- 函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。
全双工的通信基于TCP和IO多路复用。 TCP可以使客服端和服务器连接起来进行通信。
思路:
先建立客服端和服务端的通信
服务端:
1.创建套接字(socket)
2.将ip号和端口号绑定到套接字中(bind)
3.监视(将主动套接字转换为被动套接字)(listen)
4.阻塞函数等待客服端连接(accept)
5.进行io多路复用完成通信(select fd_set)()
客服端:(客服端和服务端的基本操作基本一样)
1.创建套接字(socket)
2.连接服务器()
5.进行io多路复用完成通信(select fd_set)
直接上代码: 服务器:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<stdio.h>
#include<string.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <arpa/inet.h>
//建立服务器与客服端完成全双工通讯,使用TCP和IO复用
int main(int argc, char const *argv[])
{
//1.创建套接字
int sock;
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)//容错判断
{
perror("sock_stream err\n");
return -1;
}
//2.端口号和IP号绑定
struct sockaddr_in add;
add.sin_addr.s_addr=inet_addr(argv[1]);//ip号
add.sin_family=AF_INET;//ipv4协议
add.sin_port=htons(atoi(argv[2]));//端口号
int len=sizeof(add);
if(bind(sock,(struct sockaddr*)&add,len)<0)
{
perror("inet_addr err\n");
return -1;
}
//3.监听
if(listen(sock,8)<0)
{
perror("listen err\n");
return -1;
}
//4.等待连接时会阻塞
int sockfd;
sockfd=accept(sock,NULL,NULL);
if(sockfd<0)
{
perror("sockfd err\n");
return -1;
}
//5.使用io多路复用与客服端
//5.1创建表
fd_set readig,flag;
FD_ZERO(&readig);
FD_SET(0,&readig);
FD_SET(sockfd,&readig);
int max=sockfd;
char buf[64]="";
while(1)
{
flag=readig;
int revt=select(max+1,&flag,NULL,NULL,NULL);//监听表
if(revt<0)
{
perror("select err\n");
return -1;
}
if(FD_ISSET(0,&flag))
{
gets(buf);
write(sockfd,buf,64);
memset(buf,0,64);
}
if(FD_ISSET(sockfd,&flag))
{
int rea=read(sockfd,buf,64);
if(rea>0)
{
printf("%s\n",buf);
memset(buf,0,64);
}
else if(rea==0)
{
printf("客服端关闭\n");
break;
}else
{
perror("错误\n");
break;
}
}
}
close(sockfd);
return 0;
}
客服端:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include<stdio.h>
#include <arpa/inet.h>
#include<string.h>
//基于TCP,创建全双工客服端 使用标准输入0,标准输出用使用套接字用io多路复用
int main(int argc, char const *argv[])
{
if(argc!=3)
{
printf("输入ip号和端口号:\n");
return -1;
}
//1.创建套接字
int sock;
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("sock err\n");
return -1;
}
//2.连接服务器
struct sockaddr_in add;
add.sin_addr.s_addr=inet_addr(argv[1]);
add.sin_family=AF_INET;
add.sin_port=htons(atoi(argv[2]));
int len=sizeof(add);
if(connect(sock,(struct sockaddr*)&add,len)<0)//连接服务器
{
perror("inet_addr err\n");
return -1;
}
//3.使用io多路复用来判断输入输出实现全双工
fd_set readfds,tempfds;
FD_ZERO(&readfds);
FD_SET(0,&readfds);
FD_SET(sock,&readfds);
int max=sock;
char buf[64]="";
while(1)
{
tempfds=readfds;
int ret=select(max+1,&tempfds,NULL,NULL,NULL);
if(ret<0)
{
perror("select err\n");
return -1;
}
if(FD_ISSET(0,&tempfds))
{
gets(buf);
write(sock,buf,64);
memset(buf,0,64);
}
if(FD_ISSET(sock,&tempfds))
{
read(sock,buf,64);
printf("%s\n",buf);
memset(buf,0,64);
}
}
close(sock);
return 0;
}
运行结果:
欢迎大家在评论区讨论!