网络编程(5):select模型

一、select模型:
在这里插入图片描述

select(
    _In_ int nfds,
    _Inout_opt_ fd_set FAR * readfds,
    _Inout_opt_ fd_set FAR * writefds,
    _Inout_opt_ fd_set FAR * exceptfds,
    _In_opt_ const struct timeval FAR * timeout
    );//第一个参数在windows没有意义,在其他系统中是fd_set中所有描述符socket的范围+1,第二到第四个参数分别为可读、可写、异常的文件描述符集合地址,最后一个参数为时间设置(成为非阻塞的关键)

取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。
​执行FD_ZERO(&set);则set用位表示是0000,0000。
​若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)
​若再加入fd=2,fd=1,则set变为0001,0011(表示要被监控的文件
​执行select(6,&set,0,0,0)阻塞等待(因为最大的描述符为5,因此传入6
​若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011,将没有发生改变的都清零

struct timeval {
        long    tv_sec;         /* seconds */
        long    tv_usec;        /* and microseconds */
};//第一个参数为秒,第二个参数为毫秒

服务器改进:

while (true) {
		fd_set fdRead;
		FD_ZERO(&fdRead);
		FD_SET(sock, &fdRead);

		for (int i = 0; i < clients.size(); i++) 
			FD_SET(clients[i], &fdRead);

		timeval t = {5,0};
		int ret = select(0, &fdRead, nullptr,nullptr, &t);
		if (ret == 0) cout << "连接超时" << endl;
		else if (ret < 0) {
			cout << "select任务结束,返回错误" << endl;
			break;
		}
		if (FD_ISSET(sock, &fdRead))//判断fdRead集合中是否包含sock,包含了表明发生了改变
		{
			FD_CLR(sock, &fdRead);
			sockaddr_in client = {};
			int nAddrLen = sizeof(sockaddr_in);
			SOCKET cSock = accept(sock, (sockaddr*)&client, &nAddrLen);//生成新的套接字
			if (cSock != SOCKET_ERROR) cout << cSock << "连接成功" << endl;
			NewUserJoin user;
			user.id = (int)cSock;
			for (int i = 0; i < clients.size(); i++)
				send(clients[i], (char*)&user, user.dataLength, 0);
			clients.push_back(cSock);
		}
		
		for (int i = 0; i < clients.size(); i++)
			if (FD_ISSET(clients[i], &fdRead)) {//需要判断每一个socket是否发生了改变
				int ret = processor(clients[i]);
				if (ret == -1) clients.erase(clients.begin() + i);
			}
	}

客户端改进:

	while (true) {
		fd_set fdRead;
		FD_ZERO(&fdRead);
		FD_SET(sock, &fdRead);
		timeval t1 = { 5,0 };
		int ret = select(sock + 1, &fdRead, nullptr, nullptr, &t1);
		if (ret == 0) {
			Login login = {};
			strcpy_s(login.username, "qwe");
			strcpy_s(login.password, "asd");
			send(sock, (char*)&login, login.dataLength, 0);
		}
		else if (ret < 0) {
			cout << "select任务结束1" << endl;
			break;
		}
		else {
			if (FD_ISSET(sock, &fdRead)) {
				FD_CLR(sock, &fdRead);
				if (processor(sock) == -1) {
					cout << "select任务结束2" << endl;
					break;
				}
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值