试想一下,有没有一种方法可以将异步的程序改为同步,而又持有异步的效果呢?

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的解决思路

  1. 同时检测多个socket的状态
  2. 将需操作的socket放入一个集合中
  3. 如果没有可读写的socket就阻塞挂起

select 原型

public static void Select(
    IList checkRead, // 返回可读 Socket List
    IList checkWrite,   // 可写
    IList checkError,   // 错误
    int microSeconds    // 超时时间
)

【2020 年 1 月 17 日 18:40:19 下午】
继续更新

使用 Select 时,我们需要定义几个列表,如上面原型所示这些列表应当实现了 IList 接口。

  1. 创建可读列表CheckRead
  2. 将所有连接Socket放入CheckRead中
  3. 使用Socket.Select()对checkRead中的可读socket进行筛选
  4. 对筛选后的可读对象进行读取

通过以上步骤,我们就使用 Select 完成了筛选,非常简单吧!

从下一章开始按书的进度,我们就使用学习到的 Socket 知识写一个多人大乱斗游戏试试吧 ✌️ ~