服務器select模型

    多路轉接I/O服務器中的一種:select服務器,該模型的服務器是將文件描述符放入隊列中保存並監聽,以輪詢的機制去監聽這些文件描述符,當相對應的文件描述符有讀請求、寫情況或異常發生時,對應的位將發生變化。select模型需要對所有監聽的套接字實行輪詢監聽處理,當需要監聽的套接字過多時,就可能出現響應不及時等問題,從而降低了服務器性能。

下面是服務器的實現(服務器將客戶端發送過來的數據全部轉換爲大寫)

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>

int main(int argc, char const *argv[])
{
	//創建套接字
	int listen_fd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==listen_fd)
	{
		perror("socket");
		return ;
	}
	//構造地址結構
	struct sockaddr_in seraddr;
	memset(&seraddr,0,sizeof(seraddr));
	seraddr.sin_family=AF_INET;
	seraddr.sin_port=htons(1234);
	seraddr.sin_addr.s_addr=inet_addr("192.168.1.30");
	//將地址結構和套接字綁定
	if(bind(listen_fd,(struct sockaddr*)&seraddr,sizeof(seraddr))==-1)
	{
		perror("bind");
		return ;
	}
	//設置連接隊列數目
	if(listen(listen_fd,10)==-1)
	{
		perror("listen");
		return ;
	}
	int maxfd=listen_fd;
	fd_set readset;
	struct timeval ts;
	ts.tv_sec=1;
	int clifd[128];
	int i,index=0;
	for(i=0;i<128;i++)
	{
		clifd[i]=-1;
	}

	while(1)
	{
		FD_ZERO(&readset);//清除
		FD_SET(listen_fd,&readset);//將listen_fd放到監聽隊列
		for(i=0;i<index;i++)
		{
			FD_SET(clifd[i],&readset);
		}
		//監聽
		int ret=select(maxfd+1,&readset,NULL,NULL,&ts);
		if(ret==-1)
		{
			perror("select");
			return ;
		}
		//有請求發生
		if(ret>0)
		{
			//新的連接
			if(FD_ISSET(listen_fd,&readset))
			{
				struct sockaddr_in cliaddr;
				memset(&cliaddr,0,sizeof(cliaddr));
				int cli_size=sizeof(cliaddr);
				int fd=accept(listen_fd,(struct sockaddr*)&cliaddr,&cli_size);
				if(-1==fd)
				{
					perror("accept");
					return ;
				}
				clifd[index]=fd;
				if(clifd[index]>maxfd)
				{
					maxfd=clifd[index];
				}
				index++;
				printf("index:%d\n",index);
			}
			for(i=0;i<index;i++)
			{   //數據處理
				if(FD_ISSET(clifd[i],&readset))
				{
					char buf[1024];
					int j=0;
					int len=read(clifd[i],buf,sizeof(buf)-1);
					buf[len]='\0';
					printf("%s\n",buf);
					while(buf[j]!='\0')
					{
						if(buf[j]>='a' && buf[j]<='z')
						{
							buf[j] -= 0x20;
						}
						j++;
					}
					write(clifd[i],buf,strlen(buf));
				}
			}
		}
	}

	return 0;

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章