有没有办法在 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:仅当有更新时才从服务器获取数据,否则从缓存中获取