select和poll服务器实现(Linux)

select是一个系统调用和应用程序编程接口(API)在类Unix和POSIX兼容的操作系统用于检查的状态文件描述符打开输入/输出通道。选择系统调用是类似的调查在UNIX System V和更高版本的操作系统推出设施.

函数如下:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);


fd_set type参数可以具有四个工具宏来处理:FD_SET(),FD_CLR(),FD_ZERO() ,和FD_ISSET() 。(这里便不细说了,有疑问的读者可以man)

选择回报位设置总数readfds,writefds和errorfds,或零如果超时到期,-1。

文件描述符在选择所使用的集合是有限的大小,取决于操作系统。较新的系统调用轮询提供了更灵活的解决方案。


select服务器代码如下

<span style="font-size:18px;">#include<stdio.h>
#include<sys/socket.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<sys/time.h>

char fds[128];
#define COUNT   sizeof(fds)/sizeof(fds[0])
   int max_fd = 0;

static void guse(const char* prac)
{
printf("%s [ip] [port]..\n",prac);
}

static int my_select(const char* _ip, const int _port){
	int sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock < 0){
		perror("create socket error...");
		exit(1);

	}
	
	struct sockaddr_in server_socket;
	bzero(&server_socket,sizeof(server_socket));
	server_socket.sin_family = AF_INET;
	server_socket.sin_addr.s_addr =inet_addr(_ip);
	server_socket.sin_port = htons(_port);
	
	int opt = 1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	
	if(bind(sock,(struct sockaddr*)&server_socket,sizeof(server_socket))< 0)
	{
		perror("bind error ...");
		exit(2);
	}
	
	if(listen(sock,5) < 0 ){
		perror("listen errno ...");
		close(sock);
		 exit(3);
	}

	return sock;
}

static void init_fd_arr()
{

   int i = 0;
   for(;i<COUNT;i++){
	   fds[i] = -1;
   }
}

static int add_fd_arr(int fd){

   int i = 0;
   for(;i<COUNT;i++){
	   if(fds[i] == -1){
		   fds[i] = fd;
		   return 0;
	   }
   }
   return i;
}

static int remove_arr(int fd){
	int i = 0;
	for(; i < COUNT; i++){
		if(fds[i] == fd){
			fds[i] = -1;
			break;
		}
	}
	return 0;
}

static int setifd(fd_set * fdset){
	int i = 0;
	for(;i<COUNT;i++){
		if(fds[i] != -1 ){
			FD_SET(fds[i],fdset);
			if(fds[i]>max_fd)
				max_fd = fds[i];
		}
	}
	return 0;
}

int main(int argc,char* argv[])
{
   if(argc != 3)
 {
   guse(argv[0]);
     exit(0);
 }
   init_fd_arr();
   int listen_sock =  my_select(argv[1], atoi(argv[2]));
   add_fd_arr(listen_sock);
   fd_set red;
    FD_ZERO(&red);
   while(1){
       setifd(&red);
	   FD_SET(listen_sock,&red);
        struct timeval _timeout ={5,0};
		switch(select(max_fd+1,&red,NULL,NULL,&_timeout)){
			case -1:
				printf("selsect errno..\n");
				exit(4);
				break;
			case 0:
				printf("Time out \n");
				break;
			default:
				{
					int index = 0;
					for(;index < COUNT; index++){
						if(fds[index] != -1 && FD_ISSET(fds[index],&red)){

	            struct sockaddr_in peer;
				int addrlen = sizeof(peer);
				int ret = accept(listen_sock,(struct sockaddr*)&peer,&addrlen);
				if(ret  < 0){
					perror("accept error...\n");
					close(ret);
					exit(4);
						}else
						{
							if(1 == add_fd_arr(ret)){
								printf("full ...\n");
									close(ret);
							}
						}
                printf("Yougot a connection from cient's ip is %s, prot is %d\n",inet_ntoa(peer.sin_addr),htons(peer.sin_port));
				continue;
					}
				}
					if(fds[index] != -1 && FD_ISSET(fds[index],&red)){

				char buf[1024];
                memset(buf,'\0',sizeof(buf));
				ssize_t _s = read(fds[index],buf,sizeof(buf)-1);
				if(_s == 0){
					printf("client close ...\n");
				}
				else if(_s < 0)
				{
					printf("errno  read..\n");
				}
				else{
					printf("server:%s",buf);
				}
					}


				}
				break;
		}
   }

return 0;
}
</span>

首先我们来看看这个这个程序的结果:


可以看出,这个程序跟上一篇TCP服务器的功能是一样的。至于客户端,读者可以去看上一篇博文,这篇文章便不再叙说。



poll:



<span style="font-size:18px;">#include<stdio.h>
#include<poll.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	struct pollfd polls[1];
	polls[0].fd = 0;
	polls[0].events = POLLIN;
	polls[0].revents = 1;
	int times = 5000;

	char buf[1024];
	while(1)
	{
	switch(poll(polls,1,times)){
		case -1:
			printf("poll error...\n");
			exit(0);
			break;
		case 0:
			printf("Time OUT ...\n");
			break;
		default:
			{
				memset(buf,'\0',sizeof(buf));
			    read(1,buf,sizeof(buf));
				printf("%s\n",buf);
				
				
			}
			break;

	}
	}
	return 0;
}
</span>

这个程序的功能是你输入一个字符,然后服务器给你返回那个值:





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值