select


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

管理多个IO事件;

int nfds :要管理的事件最大值+1;

fd_set *readfds: 关注可读事件,和connect 事件

fd_set *writefds:关注可写事件

fd_set *exceptfds:关注异常事件

struct timeval *timeout:设定超时时间,如果设置为NULL,则一直等待有事件到来,如果不为NULL则等待设定时间

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); 清空文件描述符

详细请参考:点击打开链接

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string>
#include <memory.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>

#define BUFFSIZE 1024
#define PORT 5588
using namespace std;

template<typename T>
void log(T msg)
{
	cout<<msg<<endl;
}

int initSock()
{
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	struct sockaddr_in sockaddr_t;
	memset(&sockaddr_t, 0, sizeof(sockaddr_t));
	sockaddr_t.sin_family = AF_INET;
	sockaddr_t.sin_port = htons(PORT);
	sockaddr_t.sin_addr.s_addr = htonl(INADDR_ANY);

	/*设置为非阻塞*/
	// int flags = fcntl(fd, F_GETFL, 0);
	// fcntl(fd, F_SETFL, flags|O_NONBLOCK);

	//设置地址重复利用
	int on = 1;
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
	{
		log("setsockopt");
	}
	
	if (bind(fd, (struct sockaddr*)&sockaddr_t, sizeof(sockaddr_t)) < 0 )
	{
		log("bind is failed");
		return -1;
	}

	if(listen(fd, SOMAXCONN) < 0)
	{
		log("listen is failed");
		return -1;
	}
	return fd;
}


int acceptPool(int fd)
{
	int acceptfd;
	
	struct sockaddr_in clientAddr;
	socklen_t len = sizeof(clientAddr);
	fd_set rset;
	fd_set allset;
	FD_ZERO(&rset);
	FD_ZERO(&allset);
	FD_SET(fd, &allset);

	int clientfds[FD_SETSIZE];
	memset(clientfds, -1, sizeof(clientfds));
	int retval = 0;
	int MAX = fd;
	char readbuff[1024];
	int i = 0;
	while(true)
	{
		rset = allset;
		retval = select(MAX + 1, &rset, NULL, NULL, NULL);
		if (retval < 0)
		{
			if (retval == EINTR)
			{
				log("select error is EINTR");
				continue;
			}
			else
			{
				return -1;
			}
		}
		else if(retval == 0)
		{
			continue;
		}
		else
		{
			if (FD_ISSET(fd, &rset))//查看是否为connect 事件
			{
				acceptfd = accept(fd,(struct sockaddr*)&clientAddr, &len);
				if (acceptfd < 0 )
				{
					continue;
				}
				for (i = 0; i < FD_SETSIZE; ++i)
				{
					if (clientfds[i] < 0)
					{
						clientfds[i] = acceptfd;
						break;
					}
				}
				if (i == FD_SETSIZE)
				{
					log("too many clients ");
					exit(0);
				}
				if (MAX < acceptfd)
				{
					MAX = acceptfd;
				}

				FD_SET(acceptfd, &allset);
				if (--retval <= 0)
				{
					continue;
				}
			}

			for (int i = 0; i < FD_SETSIZE; ++i)
			{
				if (clientfds[i] < 0)
				{
					continue;
				}
				acceptfd = clientfds[i];
				if (FD_ISSET(acceptfd, &rset))
				{
					memset(readbuff, 0, sizeof(readbuff));
					int n = read(acceptfd, readbuff, sizeof(readbuff));
					if (n < 0)
					{
						log("read error");
						exit(0);
					}
					else if (n == 0)
					{
						log("client is close");
						close(acceptfd);
						clientfds[i] = -1;
						FD_CLR(acceptfd, &allset);
						continue;
					}
					log(readbuff);
					write(acceptfd, readbuff, strlen(readbuff));
					if (--retval <= 0)
					{
						break;
					}
				}	
			}
			

		}
		

		
		// pthread_t thread;
		// pthread_create(&thread, NULL, pool, (void*)&acceptfd);
	}
	return 0;
}

int main(int argc, char const *argv[])
{
	int fd = initSock();
	acceptPool(fd);
	return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值