linux c IO多路复用之select函数模型,构建C/S来实现服务器与客户端之间进行通信

//"util.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/select.h>
#define backlogs 10
#define BUF_SIZE 50
int Socket(int domain,int type,int protocol)
{
	int fd=socket(domain,type,protocol);
	if(fd==-1)
		return -1;
	return fd;
}
int Bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
{
	int ret=bind(sockfd,addr,addrlen);
	if(ret==-1)
		return -1;
	return ret;
}
int Listen(int sockfd,int backlog)
{
	int ret=listen(sockfd,backlog);
	if(ret==-1)
		return -1;
	return ret;
}
int start_up(const char* ip,int port)
{
	int fd=Socket(AF_INET,SOCK_STREAM,0);
	struct sockaddr_in ser_addr;
	ser_addr.sin_family=AF_INET;
	ser_addr.sin_port=htons(port);
	ser_addr.sin_addr.s_addr=inet_addr(ip);
	int on=1;
	setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
	socklen_t addrlen=sizeof(struct sockaddr);
	Bind(fd,(struct sockaddr*)&ser_addr,addrlen);
	Listen(fd,backlogs);
	return fd;
}

//ser.c 服务器端
#include"util.h"
int main(int argc,char *argv[])
{
	int i,j,n,maxi;
	int nready,client[FD_SETSIZE];//FD_SETSIZE  1024
	int maxfd,listenfd,connfd,sockfd;
	char buf[BUF_SIZE];
	char str[INET_ADDRSTRLEN];//16
	struct sockaddr_in clie_addr,serv_addr;
	socklen_t clie_addr_len;
	fd_set rset,allset;
	listenfd=start_up(argv[1],atoi(argv[2]));
	maxfd=listenfd;             //起初listenfd 即为最大文件描述符
	maxi=-1;                    //将来用作client[]的下标,初始值指向下标为-1的位置
	for(i=0;i<FD_SETSIZE;i++)//1024
		client[i]=-1;//用-1初始化client
	FD_ZERO(&allset);
	FD_SET(listenfd,&allset);         //构造select监控文件描述符集

	while(1)
	{
		rset=allset;                  //每次循环时都从新设置select监控信号集
		nready=select(maxfd+1,&rset,NULL,NULL,NULL);//rset在select返回后在改变  //没有发生可读事件的fd将被置0
		if(nready<0)
		{
			perror("select error\n");
			continue;
		}
		if(FD_ISSET(listenfd,&rset))        //说明有新的客户端连接
		{
			clie_addr_len=sizeof(struct sockaddr);
			connfd=accept(listenfd,(struct sockaddr *)&clie_addr,&clie_addr_len);//accept() 不会阻塞
			printf("received from %s at PORT %d\n",
					inet_ntop(AF_INET,&clie_addr.sin_addr,str,sizeof(str)),
					ntohs(clie_addr.sin_port));
			for(i=0;i<FD_SETSIZE;i++)
			{
				if(client[i]==-1)
				{
					client[i]=connfd;    //保存accept返回的文件描述符到client[]里
					break;
				}
			}
			if(i==FD_SETSIZE)            //达到select能监控的文件个数上限1024
			{
				fputs("too many clients!!! ,The Ser is Load",stderr);
				exit(1);
			}
			FD_SET(connfd,&allset);
			if(connfd>maxfd)
				maxfd=connfd;
			if(i>maxi)
				maxi=i;
			if(--nready==0)
				continue;
		}
		for(i=0;i<=maxi;i++)
		{
			if( (sockfd=client[i])<0)
				continue;
			if(FD_ISSET(sockfd,&rset))
			{
				if( (n=recv(sockfd,buf,sizeof(buf),0))==0 ) 
				{
					close(sockfd);
					FD_CLR(sockfd,&rset);
					client[i]=-1;
				}
				else if(n>0)
				{
					for(j=0;j<n;j++)
						buf[j]=toupper(buf[j]);
					send(sockfd,buf,n,0);
				}
				if(--nready==0)
					break;
			}
		}
	}
	close(listenfd);
	return 0;
}

//客户端
//cli.c
#include"util.h"
int main(int argc,char *argv[])
{
	char sendbuf[128];
	char recvbuf[128];
	socklen_t addrlen=sizeof(struct sockaddr);
	int cli_fd=socket(AF_INET,SOCK_STREAM,0);
	if(cli_fd==-1)
		return -1;
	struct sockaddr_in seraddr;
	seraddr.sin_family=AF_INET;
	seraddr.sin_port=htons(atoi(argv[2]));
	seraddr.sin_addr.s_addr=inet_addr(argv[1]);
	int ret=connect(cli_fd,(struct sockaddr*)&seraddr,addrlen);
	if(ret==-1)
	{
		perror("connect error!\n");
		return -1;
	}
	else
		printf("success\n");
	while(1)
	{
		printf("Cli:>");
		scanf("%s",sendbuf);
		send(cli_fd,sendbuf,strlen(sendbuf)+1,0);
		recv(cli_fd,recvbuf,128,0);
		printf("From Self Cli:%s\n",recvbuf);
	}
	close(cli_fd);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值