C# Microsoft推荐套接字

C# Microsoft推荐套接字,c#,sockets,C#,Sockets,我有一个关于以前代码的Microsoft推荐文档,即: 此代码明确依赖NetworkStream.DataAvailable属性。虽然这并不是不正确的,但却是正确的 效率不是很高,因为它强制代码在带有嵌套Thread.Sleep调用的循环中测试此属性, 这会增加每秒线程上下文切换的数量,并可能导致 CPU使用率增加 此外,这并不意味着没有使用Socket.ReceiveTimeout值,因为Socket是在阻塞模式下配置的,因此NetworkStream.Read调用可能会阻塞 上述代码的第二

我有一个关于以前代码的Microsoft推荐文档,即:

此代码明确依赖NetworkStream.DataAvailable属性。虽然这并不是不正确的,但却是正确的 效率不是很高,因为它强制代码在带有嵌套Thread.Sleep调用的循环中测试此属性, 这会增加每秒线程上下文切换的数量,并可能导致 CPU使用率增加

此外,这并不意味着没有使用Socket.ReceiveTimeout值,因为Socket是在阻塞模式下配置的,因此NetworkStream.Read调用可能会阻塞

上述代码的第二个问题是,它假定单个读取操作将读取整个主机响应。虽然这对于小读取是正确的,但套接字API不能保证这一点,并且可能导致部分读取

如果数据连接器没有主机通信协议的内部知识,这将很难处理,因为它需要能够解释从套接字读取的数据,以检测响应消息是否已完全读取

此外,如果发生部分读取,一旦引入连接池,这可能会导致重大问题。考虑下面的场景:

网站上的事务从池中获得新连接,并向主机发送请求。 主机以1526字节的响应进行响应。 连接对象尝试从套接字读取,但仅读取1345字节。 因为连接认为它已经从套接字读取了整个响应,所以它将连接返回到池并继续。 现在,想象一下,当网站上的第二笔交易出现时,要求 来自池的连接,并获取第一种情况中使用的相同连接:

代码从池中获取连接,并向主机发送新的请求消息 主机以新的1520 by response进行响应 连接尝试从套接字读取数据并返回1701字节。 也就是说,它获取第一次调用期间最初未读取的剩余181字节,以及 完成第二次操作的响应。当调用方尝试时,这可能会导致错误 分析主机响应并发现其格式不正确

推荐 强烈建议避免依赖套接字读取读取主机发送的全部消息, 虽然在正常情况下大多数情况下都会发生这种情况,但在负载或负载下很容易发生断裂 网络拥塞

通过本文的介绍,我一直在研究如何解决这个问题,但是,所有示例都使用了我使用的相同解决方案

// message buffer
Byte[] dataByte = new Byte[RES_SIZE]; 
int readedBytes = 0; 

do // wait....
{ 
    Thread.Sleep(Delay); 
    message = string.Format("Waiting for messages, check number #{0}", readedBytes); 

} while (!networkStream.DataAvailable); 
//
// check for message
if (networkStream.DataAvailable)
{ 
    readedBytes = networkStream.Read(dataByte, 0, RES_SIZE); 
    //...
    //...
    //...
} 
问题: 我如何解决这个问题?

阅读套接字中的选择方法。它获取套接字列表并返回具有可用数据的套接字

这允许您使用一个循环检查x套接字,然后在单独的线程/任务中处理包含数据的套接字


事实上,我们对此进行了一些很好的讨论。这是《C中的TCP/IP套接字:程序员实用指南》一书的节选。

此外,除了网络流之外,数据可用的while循环几乎适用于任何流,因为您的读取速度几乎总是比发送的所有字节都快。@Silvermind Thread。睡眠确实确保了CPU负载的增加,通过强制上下文切换。@ElCote您从哪里获得此Microsoft推荐文档的?睡眠几乎总是一种错误的方式。@PeterRitchie,这不是我的意思,但我本可以更清楚地了解这一点。在这种情况下,如果没有Thread.Sleep,它将消耗比Thread.Sleep更多的cpu。使用它是否是一个好主意,不是我评论中的问题。我在考虑:并可能导致CPU使用率有所增加。我建议使用异步IO而不是轮询。我发现很难相信微软建议在套接字上进行数据轮询。
do // wait....
{
    //
    //
    //
} while (!networkStream.DataAvailable);