23062网络编程day5

根据select TCP服务器流程图编写服务器

#include 
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__:",__LINE__);\
	perror(msg);\
}while(0)

#define PORT 8888
#define IP "192.168.114.104"

int keyboard_events(void);
int cliConnect_events(int,struct sockaddr_in*,fd_set*,int*);
int cliRcvSnd_events(int,struct sockaddr_in*,fd_set*,int*);

int main(int argc, const char *argv[])
{
	//创建流式套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("socket create success\n");
	//允许端口快速地被复用
	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速地被复用成功\n");
	//填充地址信息结构体用于bind绑定
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);
	//绑定服务器的地址信息
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success\n");
	//设置套接字为被动监听状态
	if(listen(sfd,128)<0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success\n");
	//创建一个读集合
	fd_set readfds,tempfds;
	//清空集合
	FD_ZERO(&readfds);
	//将文件描述符添加到集合中
	FD_SET(0,&readfds);
	FD_SET(sfd,&readfds);

	int maxfd=sfd;
	int s_res=-1;
	ssize_t res=-1;
	char buf[128]="";
	struct sockaddr_in saveCin[1024];

	while(1)
	{
		tempfds=readfds;
		s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
		if(s_res<0)
		{
			ERR_MSG("select");
			return -1;
		}
		else if(0==s_res)
		{
			printf("timeout\n");
			break;
		}
		printf("__%d__\n",__LINE__);

		for(int i=0;i<=maxfd;i++)
		{
			if(FD_ISSET(i,&tempfds)==0)
			continue;

			//触发键盘输入事件
			if(0==i)
			{
				printf("触发键盘输入事件\n");
				keyboard_events();
			}
			//客户端连接事件
			else if(sfd==i)
			{
				printf("触发客户端连接事件\n");
				cliConnect_events(sfd,saveCin,&readfds,&maxfd);
			}
			else
			{
				printf("触发客户端交互事件\n");
				cliRcvSnd_events(i,saveCin,&readfds,&maxfd);
			}
		}

	}

	if(close(sfd)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	return 0;
}

int keyboard_events(void)
{
	char buf[128]="";
	bzero(buf,sizeof(buf));
	fgets(buf,sizeof(buf),stdin);
	buf[strlen(buf)-1]=0;

	printf(":%s\n",buf);
	return 0;
}

int cliConnect_events(int sfd,struct sockaddr_in saveCin[],fd_set *preadfds,int* pmaxfd)
{
	int newfd=-1;
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);

	newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
	if(newfd<0)
	{
		ERR_MSG("newfd");
		return -1;
	}
	printf("[%s:%d]客户端连接成功 newfd=%d\n",\
			inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
	saveCin[newfd] = cin;

	FD_SET(newfd,preadfds);
	*pmaxfd = *pmaxfd>newfd ? *pmaxfd:newfd;
	return 0;
}


int cliRcvSnd_events(int fd,struct sockaddr_in* saveCin,fd_set* preadfds,int* pmaxfd)
{
	char buf[128]="";
	bzero(buf,sizeof(buf));

	ssize_t res=recv(fd,buf,sizeof(buf),0);
	if(res<0)
	{
		ERR_MSG("recv");
		return -1;
	}
	else if(0==res)
	{
		printf("[%s:%d]客户端下线 newfd=%d\n",\
			inet_ntoa(saveCin[fd].sin_addr),ntohs(saveCin[fd].sin_port),fd);
		close(fd);
		FD_CLR(fd,preadfds);

		while(FD_ISSET(*pmaxfd,preadfds)==0&&(*pmaxfd)-- >= 0)
		return 0;
	}
		printf("[%s:%d] newfd=%d  :  %s\n",\
			inet_ntoa(saveCin[fd].sin_addr),ntohs(saveCin[fd].sin_port),fd,buf);

		strcat(buf,"*_*");
		if(send(fd,buf,sizeof(buf),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
		printf("send success\n");
		return 0;
}

思维导图

 23062网络编程day5_第1张图片

你可能感兴趣的:(网络)