select用法 多并发处理

select默认最大检查套接口数量是1024,有定义

#define __NFDBITS	(8 * sizeof(unsigned long))
#define __FD_SETSIZE	1024

#define __FDSET_LONGS	(__FD_SETSIZE/__NFDBITS)

typedef struct {
	unsigned long fds_bits [__FDSET_LONGS]; //1024
} __kernel_fd_set

1. 理解select

1.假设fd_set长度1字节
2.FD_ZERO(&set)。set = 0000 0000
3.fd = 3,FD_SET(fd, &set)。set = 0000 0100
4.fd = 6,FD_SET(fd, &set)。set = 0010 0100
4.执行select(fd + 1, &set, NULL, NULL, &tv)阻塞等待
5.若fd = 3可读,则select返回。set = 0000 0100(其他的fd被清空)

2. select

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

readfds:select监视的可读文件句柄集合
writefds:select监视的可写文件句柄集合
exceptfds:select监视的异常文件句柄集合
timeout:本次select()的超时结束时间 (见/usr/sys/select.h)
当readfds或writefds中映象的文件可读或可写或超时,本次select() 就结束返回
select不断修改timeout的值,进入下一次阻塞时,需要重新设置timeout时间

3. FD_CLR

void FD_CLR(int fd, fd_set *set);

从集合set中删除描述字fd

4. FD_ISSET
int FD_ISSET(int fd, fd_set *set);
测试fd是否是集合set中一员

5. FD_SET

void FD_SET(int fd, fd_set *set);

向集合set添加描述字fd

6. FD_ZERO

void FD_ZERO(fd_set *set);

将set初始化为空集NULL

7. 举例

while(1)
{
	struct timeval tv; //根据需要
	fd_set readfds;
	
	FD_ZERO(&readfds); //每次必须清空
	FD_SET(sock, &readfds); //设置的套接字必须是存在的,不然select报错
	
	result = select(FD_SETSIZE, &readfds, NULL, NULL, &tv);
	if (result < 0)
	{   
		if (errno != EINTR)
		{   
			fprintf(stderr, "Error in select(): %d %s
", errno, strerror(errno));
		}   
	}   
	else if (result > 0)
	{   
		unsigned char buffer[MAX_PACKET_SIZE];
		int numBytes;
		
		if (FD_ISSET(sock, &readfds))
		{   
			struct sockaddr_storage addr;
			socklen_t addrLen;
			
			addrLen = sizeof(addr);
			
			numBytes = recvfrom(sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen);
		}   
	}  
}
原文地址:https://www.cnblogs.com/zhangxuechao/p/11709883.html