13.3 Linux_网络编程_多路复用I/O接入多客户端

select函数

函数声明

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

返回值:成功返回有数据的文件描述符,失败返回-1 

nfds:最大的文件描述符,值为readfds,writefds,exceptfds中最大的文件描述符+1

readfds:可读集合,常用

writefds:可写集合,不常用

exceptfds:异常集合,不常用

timeout:超时时间。NULL永久阻塞,0非阻塞

struct timeval结构体:

struct timeval {
    time_t      tv_sec;    //s        
    suseconds_t tv_usec;   //us   
};

fd_set结构体:

fd_set就是一个整型数,每一个bit位代表一个文件描述符fd。

当fd可操作时,对应的位就会自动置1,读取之后需要手动清零。操作函数如下: 

//将文件描述符从集合中删除
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);

示例代码

代码功能:

这是一个服务器端的socket,使用select以阻塞的方式去监听多个文件描述符的数据。当监听到数据后,代表数据已经到达,这时不论是调用accept还是read都是不会阻塞的,即:不会有阻塞等待数据到来的过程,会有一小段阻塞拷贝数据的过程。

当监听到的文件描述符是fd时,说明是有客户端需要接入,这时就执行accept相关操作;当监听到不为fd时,这代表是客户端发来数据,需要读取客户端的数据,那么使用循环去轮询各个客户端的套接字文件描述符,从而与客户端进行通信。

代码实现:

server.c代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
 
#define BACKLOG 5 				//最大接入客户端数量
int socket_init(char** argv);
int main(int argc ,char** argv){
 
	int fd;
	//判断参数有效性
	if(argc != 3){
		printf("param err\n");
		printf("%s<ip><port>\n",argv[0]);
		return -1;
	}
	printf("ip = %s\n",argv[1]);
	printf("port = %s\n",argv[2]);
	//初始化socket:TCP,IPv4,本地回环测试
	fd = socket_init(argv);
	//接受客户端链接
	int newFd;
	struct sockaddr_in newAddr;
	socklen_t newAddrlen;
	char buf[100] = {0};
	fd_set readfds,readfdsTmp;
	int i,nfds;
	//1.清空可读可写集合,并将服务器的fd添加进可读集合
	FD_ZERO(&readfds);
	FD_ZERO(&readfdsTmp);
	FD_SET(fd,&readfds);
	nfds = fd + BACKLOG + 1;
	while(1){
		readfdsTmp = readfds;
		//2.以阻塞方式监听全部文件描述符,如果有文件描述符可以写入,则返回
		if(select(nfds,&readfdsTmp,NULL,NULL,NULL) == -1){
			perror("select");
			exit(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值