试想一下,有没有一种方法可以将异步的程序改为同步,而又持有异步的效果呢?
Poll
意义:使用同步的方式解决异步问题。
我们分析一下之前的程序逻辑,会发现我们使用 beginxxx 来开启新线程处理新的 socket,但是我们的客户端并不是实时的于服务器进行交互的(只在进行交互时,整个线程才是有效的,平时都处于阻塞等待状态。)
有这么一种方式:if (socket 有可读数据) socket.Receive ()
if (socket 缓冲区可写) socket.Send ()
if (socket 错误) 处理错误
只要在阻塞方法前,加上一层判断,有数据可读才读,有数据可写才写,这样不就解决了程序卡住的问题吗?
Ms 提供了 Poll 方法:
public bool Poll | |
{ | |
int microSeconds;// 回应时间(ms) -1 一直等待 0 非阻塞 | |
SelectMode mode;//SelectRead 是否可读 SelectWrite 是否可写 SelectError 是否发生错误 | |
} |
使用Poll改进客户端和服务器
- 客户端 对于客户端只需要在update中加一个
if(socket.Poll(0,SelectMode.SelectRead)) 执行读取
就可以了。 - 服务器 对于服务器,需要在主循环中对所有已连接的客户端进行状态监测,在其客户端可读时(即有数据发送给服务器时)进行读取操作。
Select
意义:解决 Poll 下 Cpu 占用过高的问题
在前面没有提到cpu占用的事情,这里说一下,使用poll时,我们会在update中持续监听,程序在同一线程中非阻塞式的处理请求,会导致cpu占用过高的问题。Select的解决思路
- 同时检测多个socket的状态
- 将需操作的socket放入一个集合中
- 如果没有可读写的socket就阻塞挂起
select 原型
public static void Select( | |
IList checkRead, // 返回可读 Socket List | |
IList checkWrite, // 可写 | |
IList checkError, // 错误 | |
int microSeconds // 超时时间 | |
) |
【2020 年 1 月 17 日 18:40:19 下午】
继续更新
使用 Select 时,我们需要定义几个列表,如上面原型所示这些列表应当实现了 IList 接口。
- 创建可读列表CheckRead
- 将所有连接Socket放入CheckRead中
- 使用Socket.Select()对checkRead中的可读socket进行筛选
- 对筛选后的可读对象进行读取
通过以上步骤,我们就使用 Select 完成了筛选,非常简单吧!
从下一章开始按书的进度,我们就使用学习到的 Socket 知识写一个多人大乱斗游戏试试吧 ✌️ ~