// 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);
//...
//...
//...
}
我有一份关于以前代码的Microsoft建议书文档,即:
<小时/> 此代码显式依赖于NetworkStream.DataAvailable属性。虽然这不是不正确的,但确实如此 效率不高,因为它强制代码在嵌套的Thread.Sleep()调用的循环中测试这个属性, 这可以增加线程Context Switch /秒的数量,并可能导致一些 增加CPU使用率。
此外,这并不意味着没有使用Socket.ReceiveTimeout值,因为套接字是以阻塞模式配置的,因此无论如何NetworkStream.Read()调用都可能阻塞。
上面代码的第二个问题是它假定单个Read()操作将读取整个主机响应。虽然这对于小读取来说可能是正确的,但是这不是由Socket API保证,并且可能导致部分读取。
如果数据连接器不具备主机通信协议的内部知识,这将非常难以处理,因为它需要能够解释从套接字读取的数据以检测响应消息是否被完全读取。
此外,如果发生部分读取,一旦引入连接池,这可能会导致严重问题。请考虑以下情形:
现在,想象一下当网站上的第二笔交易出现时会发生什么,请求a 来自池的连接并获得第一种情况下使用的相同连接:
也就是说,它获得了在第一次调用期间最初未读取的剩余181个字节,以及 完成第二次操作的响应。这可能会在调用者尝试时导致错误 解析主机响应并发现它是格式错误的。
建议的 强烈建议避免依赖Socket读取读取主机发送的整个消息, 虽然这种情况大部分时间都会在正常情况下发生,但这很容易在负载下或在负载下发生 网络拥塞。
的
有了这个介绍,我一直在寻找如何解决这个问题,但是,所有的例子都使用我使用的相同解决方案。
do // wait....
{
//
//
//
} while (!networkStream.DataAvailable);
问题: 我该如何解决这个问题?
答案 0 :(得分:0)
读取socket中的SELECT方法。它需要一个套接字列表并返回那些有数据的套接字。
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.select(v=vs.110).aspx
这允许你有一个循环检查x套接字,然后在单独的线程/任务中处理带有数据的循环。
实际上有一些很好的讨论。它摘自“C#中的TCP / IP套接字:程序员实用指南”一书。