linux编程---IO复用---select
2017-08-09 13:10
363 查看
与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,
也不必维护这些进程/线程,从而大大减小了系统的开销。
/* According to POSIX.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
//将一个给定的文件描述符从集合中删除
void FD_CLR(int fd, fd_set *set);
// 检查集合中指定的文件描述符是否可以读写
int FD_ISSET(int fd, fd_set *set);
//将一个给定的文件描述符加入集合之中
void FD_SET(int fd, fd_set *set);
//清空集合
void FD_ZERO(fd_set *set);
实例如下
用select实现多客户接入服务器
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<sys/types.h>
#define MAXBUF 512
#define BACKLGO 10
int conn_amount;
int fd_cli[BACKLGO];
void showclient()
{
int i;
printf("client amount: %d\n", conn_amount);
for (i = 0; i < BACKLGO; i++) {
printf("[%d]:clifd[%d]\t", i, fd_cli[i]);
}
printf("\n\n");
}
int main(int argc,char* argv[])
{
int serverfd,clifd,i;
socklen_t len;
struct sockaddr_in serveraddr,cliaddr;
unsigned int serverport,lisnum;
char buf[MAXBUF+1];
fd_set rfds;
struct timeval tv;
int ret,maxfd = -1;
serverport = 4332;
lisnum = 5;
socklen_t clilen = sizeof(struct sockaddr);
if((serverfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket");
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(serverport);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(serverfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr)) < 0)
{
perror("bind");
exit(-1);
}
if(listen(serverfd,lisnum) < 0)
{
perror("listen");
exit(-1);
}
for(i = 0;i<BACKLGO;i++)
fd_cli[i] = 0;
maxfd = serverfd;
while(1)
{
FD_ZERO(&rfds);
FD_SET(serverfd,&rfds);
FD_SET(0,&rfds);
tv.tv_sec = 30;
tv.tv_usec = 0;
for(i = 0;i<BACKLGO;i++)
{
if(fd_cli[i] != 0)
{
FD_SET(fd_cli[i],&rfds);
}
}
ret = select(maxfd + 1,&rfds,NULL,NULL,&tv);
if(ret == -1)
{
perror("select");
exit(-1);
}
else if(ret == 0)
{
continue;
}
else {
for(i = 0; i< conn_amount;i++)
{
if(FD_ISSET(fd_cli[i],&rfds))
{
ret = recv(fd_cli[i],buf,sizeof(buf),0);
char str[] = "hello client";
send(fd_cli[i],str,sizeof(str)+1,0);
if(ret <= 0)
{
printf("client fd[%d] close\n",fd_cli[i]);
close(fd_cli[i]);
FD_CLR(fd_cli[i],&rfds);
fd_cli[i] = 0;
}
else
{
if(ret < MAXBUF)
memset(&buf[ret],'\0',1);
printf("client fd [%d] send : [%s]\n",fd_cli[i],buf);
}
}
}
if(FD_ISSET(serverfd,&rfds))
{
clifd = accept(serverfd,(struct sockaddr*)&cliaddr,&clilen);
if(clifd <= 0)
{
perror("accept");
continue;
}
if(conn_amount < BACKLGO)
{
fd_cli[conn_amount++] = clifd;
printf("new client connect fd:[%d] conn_amount:[%d],ip:[%s],port:[%d]\n",fd_cli[i],conn_amount,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
if(clifd > maxfd);
maxfd = clifd;
}
else
{
printf("max connections,exit\n");
send(clifd,"sorry",6,0);
close(clifd);
break;
}
}
if(FD_ISSET(0,&rfds))
{
bzero(buf,MAXBUF + 1);
fgets(buf,MAXBUF,stdin);
if(!strncasecmp(buf,"quit",4))
{
printf("i will quit!\n");
break;
}
for(i = 0;i < conn_amount;i++)
{
len = send(fd_cli[i],buf,strlen(buf)-1,0);
if(len > 0)
printf("server send successful,%d bytes\n",len);
else
{
printf("send failed\n");
break;
}
}
}
}
showclient();
}
for(i = 0;i < BACKLGO;i++)
{
if(fd_cli[i] != 0)
{
close(fd_cli[i]);
}
}
close(serverfd);
return 0;
}
客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<sys/types.h>
#define MAXBUF 512
int main(int argc,char* argv[])
{
int clifd,len;
struct sockaddr_in serveraddr;
char buf[MAXBUF + 1];
fd_set rfds;
struct timeval tv;
int ret,maxfd = -1;
if(argc != 3)
{
printf("usage error input ip port\n");
exit(-1);
}
if((clifd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
if(inet_aton(argv[1],(struct in_addr*)&serveraddr.sin_addr.s_addr) == 0)
{
perror("inet_aton");
exit(-1);
}
if(connect(clifd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)) != 0)
{
perror("connect");
exit(-1);
}
printf("client is ready...\n");
while(1)
{
FD_ZERO(&rfds);
FD_SET(0,&rfds);
FD_SET(clifd,&rfds);
maxfd = clifd;
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(maxfd + 1,&rfds,NULL,NULL,&tv);
if(ret == -1)
{
printf("select %s\n",strerror(errno));
break;
}
else if( ret == 0)
continue;
else
{
if(FD_ISSET(clifd,&rfds))
{
bzero(buf,MAXBUF + 1);
len = recv(clifd,buf,MAXBUF,0);
if(len > 0)
printf("client fd[%d] recv %s,%d bytes\n",clifd,buf,len);
else
{
if(len < 0)
printf("client recv failed\n");
else
{
printf("server may quit\n");
break;
}
}
}
if(FD_ISSET(0,&rfds))
{
bzero(buf,MAXBUF + 1);
fgets(buf,MAXBUF,stdin);
if(!strncasecmp(buf,"quit",4))
{
printf("client will quit\n");
break;
}
len = send(clifd,buf,strlen(buf)-1,0);
if(len > 0)
{
printf("client send successful %d bytes\n",len);
}
else
printf("send failed\n");
}
}
}
close(clifd);
return 0;
}
也不必维护这些进程/线程,从而大大减小了系统的开销。
/* According to POSIX.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
//将一个给定的文件描述符从集合中删除
void FD_CLR(int fd, fd_set *set);
// 检查集合中指定的文件描述符是否可以读写
int FD_ISSET(int fd, fd_set *set);
//将一个给定的文件描述符加入集合之中
void FD_SET(int fd, fd_set *set);
//清空集合
void FD_ZERO(fd_set *set);
实例如下
用select实现多客户接入服务器
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<sys/types.h>
#define MAXBUF 512
#define BACKLGO 10
int conn_amount;
int fd_cli[BACKLGO];
void showclient()
{
int i;
printf("client amount: %d\n", conn_amount);
for (i = 0; i < BACKLGO; i++) {
printf("[%d]:clifd[%d]\t", i, fd_cli[i]);
}
printf("\n\n");
}
int main(int argc,char* argv[])
{
int serverfd,clifd,i;
socklen_t len;
struct sockaddr_in serveraddr,cliaddr;
unsigned int serverport,lisnum;
char buf[MAXBUF+1];
fd_set rfds;
struct timeval tv;
int ret,maxfd = -1;
serverport = 4332;
lisnum = 5;
socklen_t clilen = sizeof(struct sockaddr);
if((serverfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket");
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(serverport);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(serverfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr)) < 0)
{
perror("bind");
exit(-1);
}
if(listen(serverfd,lisnum) < 0)
{
perror("listen");
exit(-1);
}
for(i = 0;i<BACKLGO;i++)
fd_cli[i] = 0;
maxfd = serverfd;
while(1)
{
FD_ZERO(&rfds);
FD_SET(serverfd,&rfds);
FD_SET(0,&rfds);
tv.tv_sec = 30;
tv.tv_usec = 0;
for(i = 0;i<BACKLGO;i++)
{
if(fd_cli[i] != 0)
{
FD_SET(fd_cli[i],&rfds);
}
}
ret = select(maxfd + 1,&rfds,NULL,NULL,&tv);
if(ret == -1)
{
perror("select");
exit(-1);
}
else if(ret == 0)
{
continue;
}
else {
for(i = 0; i< conn_amount;i++)
{
if(FD_ISSET(fd_cli[i],&rfds))
{
ret = recv(fd_cli[i],buf,sizeof(buf),0);
char str[] = "hello client";
send(fd_cli[i],str,sizeof(str)+1,0);
if(ret <= 0)
{
printf("client fd[%d] close\n",fd_cli[i]);
close(fd_cli[i]);
FD_CLR(fd_cli[i],&rfds);
fd_cli[i] = 0;
}
else
{
if(ret < MAXBUF)
memset(&buf[ret],'\0',1);
printf("client fd [%d] send : [%s]\n",fd_cli[i],buf);
}
}
}
if(FD_ISSET(serverfd,&rfds))
{
clifd = accept(serverfd,(struct sockaddr*)&cliaddr,&clilen);
if(clifd <= 0)
{
perror("accept");
continue;
}
if(conn_amount < BACKLGO)
{
fd_cli[conn_amount++] = clifd;
printf("new client connect fd:[%d] conn_amount:[%d],ip:[%s],port:[%d]\n",fd_cli[i],conn_amount,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
if(clifd > maxfd);
maxfd = clifd;
}
else
{
printf("max connections,exit\n");
send(clifd,"sorry",6,0);
close(clifd);
break;
}
}
if(FD_ISSET(0,&rfds))
{
bzero(buf,MAXBUF + 1);
fgets(buf,MAXBUF,stdin);
if(!strncasecmp(buf,"quit",4))
{
printf("i will quit!\n");
break;
}
for(i = 0;i < conn_amount;i++)
{
len = send(fd_cli[i],buf,strlen(buf)-1,0);
if(len > 0)
printf("server send successful,%d bytes\n",len);
else
{
printf("send failed\n");
break;
}
}
}
}
showclient();
}
for(i = 0;i < BACKLGO;i++)
{
if(fd_cli[i] != 0)
{
close(fd_cli[i]);
}
}
close(serverfd);
return 0;
}
客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<sys/types.h>
#define MAXBUF 512
int main(int argc,char* argv[])
{
int clifd,len;
struct sockaddr_in serveraddr;
char buf[MAXBUF + 1];
fd_set rfds;
struct timeval tv;
int ret,maxfd = -1;
if(argc != 3)
{
printf("usage error input ip port\n");
exit(-1);
}
if((clifd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
if(inet_aton(argv[1],(struct in_addr*)&serveraddr.sin_addr.s_addr) == 0)
{
perror("inet_aton");
exit(-1);
}
if(connect(clifd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)) != 0)
{
perror("connect");
exit(-1);
}
printf("client is ready...\n");
while(1)
{
FD_ZERO(&rfds);
FD_SET(0,&rfds);
FD_SET(clifd,&rfds);
maxfd = clifd;
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(maxfd + 1,&rfds,NULL,NULL,&tv);
if(ret == -1)
{
printf("select %s\n",strerror(errno));
break;
}
else if( ret == 0)
continue;
else
{
if(FD_ISSET(clifd,&rfds))
{
bzero(buf,MAXBUF + 1);
len = recv(clifd,buf,MAXBUF,0);
if(len > 0)
printf("client fd[%d] recv %s,%d bytes\n",clifd,buf,len);
else
{
if(len < 0)
printf("client recv failed\n");
else
{
printf("server may quit\n");
break;
}
}
}
if(FD_ISSET(0,&rfds))
{
bzero(buf,MAXBUF + 1);
fgets(buf,MAXBUF,stdin);
if(!strncasecmp(buf,"quit",4))
{
printf("client will quit\n");
break;
}
len = send(clifd,buf,strlen(buf)-1,0);
if(len > 0)
{
printf("client send successful %d bytes\n",len);
}
else
printf("send failed\n");
}
}
}
close(clifd);
return 0;
}
相关文章推荐
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
- linux下IO复用编程select 和 epoll
- 【Linux编程】IO复用之select详解
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
- TCP IO复用 select并发服务端 Linux socket编程入门(3)
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- Linux网络编程:tcp并发服务器(I/O复用之select)
- 柳大的Linux游记·基础篇(5)select IO复用机制
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- Linux下C语言编程入门-18关于多路复用IO
- [转载] Linux下多路复用IO接口 epoll select poll 的区别
- Linux下多路复用IO接口 epoll select poll 的区别
- Linux下的socket编程实践(七) I/O多路复用技术之select模型
- Linux下多路复用IO接口epoll/select/poll的区别
- (转)Linux IO多路复用之epoll网络编程
- Linux编程I/O复用select用法备忘
- 网络编程----IO复用之select模型