有没有办法在 C# 中仅当有东西可供阅读时才轮询套接字?

Posted

技术标签:

【中文标题】有没有办法在 C# 中仅当有东西可供阅读时才轮询套接字?【英文标题】:Is there a way to poll a socket in C# only when something is available for reading? 【发布时间】:2009-08-08 19:03:59 【问题描述】:

我想知道当只有一个条件(数据可供读取)满足时,是否有办法在 c# 中轮询套接字,我知道 socket.Poll方法,但如果指定的 3 个条件中的任意数量返回 true,如下所示:MSDN: Socket.Poll

【问题讨论】:

【参考方案1】:

根据 MSDN 文档,返回 true 的原因有三个

Poll(microSeconds, SelectMode.SelectRead);

    如果 Listen() 已被调用并且连接处于挂起状态 如果有数据可供读取 如果连接已关闭、重置或终止

让我们看看我们是否可以区分它们:

    您始终知道之前是否调用过 Listen(),因此如果没有调用过,则无需考虑该原因。 好的,你去吧。 意味着您不能停留在 Poll() 调用中,需要找出真正发生的情况。一种选择是在Poll() 返回后立即检查套接字的状态。

结论:

    不需要考虑

    和3.可以通过每次返回true时检查套接字状态来处理。

所以我会选择(未经测试):

if (s.Poll(microSeconds, SelectMode.SelectRead)))

  if (!s.Connected)
    // Something bad has happened, shut down
  else
    // There is data waiting to be read"

【讨论】:

感谢大家的回复。 您应该在调用 poll 之前检查 Connected,或者在阅读之前先轮询 Write,因为无论如何 Connected 在幕后都是这样做的。【参考方案2】:

您可以使用可用的 Socket 属性。它返回有多少数据可供读取。

【讨论】:

【参考方案3】:

在 NetworkStream 类中找到了一些东西。如果数据可供读取,则属性 NetworkStream.DataAvailable 返回 true。返回处理 TcpListener 和 TcpClient 的 networkstream 对象。这是比套接字高一级的抽象层。

我发现无法从 Socket 到 NetworkStream。 NetworkStream 正在使用套接字,并且是套接字的流表示。但我不知道网络流在那里用套接字做什么。

【讨论】:

NetworkStream 也有 .CanRead 和 .CanWrite,我发现它们非常有用。【参考方案4】:

您可以在底层句柄上使用 select() 系统调用。

【讨论】:

我也是第一个想到的,但不知道这是否是暗星的真正含义。【参考方案5】:

您可以使用 Select() 方法代替 Poll()。 实际上,当使用 ILSpy(反射器工具)查看 Socket.Poll 时,内部代码正在调用套接字上的 select。

此外,在紧密循环中调用 Poll() 会增加内存分配,因为它会在每次调用时执行新的 IntPtr[]。 调用 Select() 可以让您重用数组,而不是在后台分配新数组。

【讨论】:

【参考方案6】:

如果 Listen 已被调用且连接处于挂起状态,则为 true; -或者- 如果数据可供读取,则为 true; -或者- 如果连接已关闭、重置或终止,则为 true; 否则,返回 false。

我了解您想检查第二个选项是否返回 true?检查 Poll 是否返回 true 后,可以检查连接是否打开,即;未连接、关闭、重置或终止。

如果它是打开的,那么它是第二个选项返回true。

【讨论】:

喜欢:if (m_sock.Poll(-1, SelectMode.SelectRead) && (m_sock.Connected == true)) ?

以上是关于有没有办法在 C# 中仅当有东西可供阅读时才轮询套接字?的主要内容,如果未能解决你的问题,请参考以下文章

仅当有数据时才呈现表

Firestore:仅当有更新时才从服务器获取数据,否则从缓存中获取

仅当有描述可用时才提取类别描述。

仅当有两个类并共享相同的第一个类时才选择元素

仅当有更新时,如何使用 GDI 读取 Windows 屏幕部分?

Play Framework,Scala - 仅当有新数据可用时才向客户端发送 websocket 消息