select实现io多路复用服务器
#include <myhead.h>
#define SER_IP "192.168.125.171" //服务器IP地址
#define SER_PORT 8888 //服务器端口号
int main(int argc, const char *argv[])
{
//1.创建套接字:用于接收客户端链接请求
int sfd =socket(AF_INET,SOCK_STREAM,0);
if(sfd == -1){
perror("socket error");
return -1;
}
printf("%d\n",sfd);
//设置端口号快速重用
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
perror("setsockopt error");
return -1;
}
printf("端口号快速重用成功\n");
//2.绑定IP地址和端口号
//2.1填充地址信息结构体
struct sockaddr_in buf;
buf.sin_family =AF_INET; //地址族
buf.sin_port=htons(SER_PORT);//端口号
buf.sin_addr.s_addr = inet_addr(SER_IP); //IP地址
//2.2绑定工作
int n=bind(sfd,(struct sockaddr*)&buf,sizeof(buf));
if(n==-1){
perror("bind");
return 1;
}
printf("%#x\n",buf.sin_family);
// 3.将套接字设置成被动监听状态
if(listen(sfd,128)==-1){
perror("listen ");
}
printf("listen success\n");
//4. 阻塞等待客户端连接请求
//定义地址信息结构体变量用于接收客户端的地址信息
struct sockaddr_in cin_arr[1024];
struct sockaddr_in cin;
socklen_t socklen =sizeof(cin);
fd_set readfds,tempfds;
FD_ZERO(&readfds);
FD_SET(0,&readfds);
FD_SET(sfd,&readfds);
int maxfd =sfd;
while(1){
tempfds=readfds;
int res =select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(res==0)
{
printf("time out\n");
return-1;
}else if(res ==-1)
{
perror("select error");
return -1;
}
for(int i=0;i<=maxfd;i++)
{
if(!FD_ISSET(i,&tempfds))
{
continue;
}
if(i==sfd)
{
int newfd =accept(sfd,(struct sockaddr*)&cin,&socklen);
if(newfd ==-1){
perror("accept error");
return 1;
}
printf("[%s:%d]:已连接,newfd=%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
FD_SET(newfd,&readfds);
cin_arr[newfd]=cin;
if(maxfd<newfd)
{
maxfd =newfd;
}
}
else if(i ==0)
{
char buf[128]="";
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
printf("触发键盘输入事件:%s\n",buf);
for(int i=4;i<=maxfd;i++)
{
send(i,buf,sizeof(buf),0);
}
}
else
{
char rbuf[128]="";//用于接收消息
bzero(rbuf,sizeof(rbuf));
int ret =recv(i,rbuf,sizeof(rbuf),0);
if(ret == 0)
{
printf("客户端已下线\n");
close(i);
FD_CLR(i,&readfds);
for(int j=maxfd;j<sfd;j--)
{
if(FD_ISSET(j,&readfds))
{
maxfd=j;
break;
}
}
continue;
}
printf("[%s:%d]:rbuf=%s\n",inet_ntoa(cin_arr[i].sin_addr),ntohs(cin_arr[i].sin_port),rbuf);
for(int i=4;i<=maxfd;i++)
{
send(i,rbuf,strlen(rbuf),0);
}
}
}
}
close(sfd);
return 0;
}
poll实现多路复用客服端
#include <myhead.h>
#define SER_IP "192.168.125.171" //服务器IP地址
#define SER_PORT 8888 //服务器端口号
#define CLI_IP "192.168.125171" //客户端IP地址
#define CLI_PORT 9999 //客户端端口号
int main(int argc, const char *argv[])
{
//1.创建套接字:用于接收客户端链接请求
int sfd =socket(AF_INET,SOCK_STREAM,0);
if(sfd == -1){
perror("socket error");
return -1;
}
printf("%d\n",sfd);
//设置端口号快速重用
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
perror("setsockopt error");
return -1;
}
printf("端口号快速重用成功\n");
//2.绑定IP地址和端口号
//2.1填充地址信息结构体
struct sockaddr_in buf;
buf.sin_family =AF_INET; //地址族
buf.sin_port=htons(CLI_PORT);//端口号
buf.sin_addr.s_addr = inet_addr(CLI_IP); //IP地址
//2.2绑定工作
int n=bind(sfd,(struct sockaddr*)&buf,sizeof(buf));
if(n==-1){
perror("bind");
return 1;
}
printf("bind success\n");
//3连接服务器
struct sockaddr_in cin;
cin.sin_family=AF_INET;
cin.sin_port= htons(SER_PORT);//服务器端口号
cin.sin_addr.s_addr = inet_addr(SER_IP);//服务器IP地址
//4.连接服务器
if(connect(sfd,(struct sockaddr*)&cin,sizeof(cin))==-1)
{
perror("connect error");
return -1;
}
printf("connect success\n");
//创建一个用于检测文件的描述符的容器
struct pollfd pfds[2];
pfds[0].fd =0;//表示第一个元素检测0号文件描述符
pfds[0].events =POLLIN; //要检测0号文件描述符的读事件
pfds[1].fd =sfd;//表示第二个元素检测cfd号文件描述符
pfds[1].events =POLLIN; //要检测cfd号文件描述符的读事件
//5.数据的收发
char wbuf[128]="";
while(1)
{
int res =poll(pfds,2,-1);//阻塞检测文件描述符集合中是否有事件产生
if(res == -1)
{
perror("poll error");
return -1;
}
else if(res == 0)
{
printf("time out\n");
return -1;
}
//程序执行至此,说明集合中有事件产生,接下来根据不同的事件,执行不同的函数即可
if(pfds[0].revents == POLLIN)//判断是否为终端输入
{
//从终端获取数据
fgets(wbuf,sizeof(wbuf),stdin);
wbuf[strlen(wbuf)-1]=0;
if(strcmp(wbuf,"quit")==0)
{
break;
}
//将数据发送给服务器
send(sfd,wbuf,sizeof(wbuf),0);
}
//判断是否为服务器发来消息
if(pfds[1].revents==POLLIN)
{
//接收服务器发来的消息
bzero(wbuf,sizeof(wbuf));
recv(sfd,wbuf,sizeof(wbuf),0);
printf("收到服务器的消息为:%s\n",wbuf);
}
}
close(sfd);
return 0;
}