【问题标题】:Winsock2 select() function: passing {0, 0} as timeout parameterWinsock2 select() 函数:传递 {0, 0} 作为超时参数
【发布时间】:2017-07-25 14:32:22
【问题描述】:
我正在使用<winsock2.h> 库创建基于客户端-服务器模型的多人实时游戏。对于通信部分,我决定使用非阻塞套接字,而不是阻塞套接字来消除多线程。
在客户端,我想在一个循环中处理这些任务:
- 处理用户输入(如有必要)
- 向/从服务器发送/接收数据(如果可能)
- 更新游戏数据(以恒定频率)
- 刷新屏幕(以恒定频率)
我想知道,在循环的第二部分使用超时 {0, 0} 调用 select 是否是一种不好的做法?我找到了this website,上面写着:
超时值 {0, 0} 表示 select() 将立即返回,允许应用程序轮询 select() 操作。 出于性能原因,应避免这种情况。
我真的不明白,为什么我应该避免使用它。如果有人能解释一下,我将不胜感激。
【问题讨论】:
标签:
c++
client-server
winsock2
【解决方案1】:
我真的不明白,为什么我应该避免[以零超时调用 select())。如果有人
可以解释一下,不胜感激。
如果您的线程的事件循环从不阻塞任何地方,那么您将以 100% 的 CPU 使用率旋转 CPU。这是低效的,因为您将浪费数万亿个 CPU 周期以最大速度在事件循环中毫无意义地旋转,而实际上并没有做任何工作,因此所有这些 CPU 周期将无法在其他地方使用(例如,其他程序或其他线程)在您自己的程序中)。这也会产生过多的热量并(在笔记本电脑或其他便携式设备上)很快耗尽电池电量。
更好的方法是计算你需要 select() 何时唤醒(例如,从现在到下一次你需要画一个框架,或者做一些其他的计划任务时还剩下多少时间),然后传入选择的超时参数的时间量。这将导致select() 阻塞(在您指定的时间内),因此允许您的线程在不需要做任何事情的期间休眠。这将在始终使用(至少)一个完整 CPU 内核的程序与仅使用完成其任务实际需要的最少 CPU 时间的程序之间产生差异。