首页 新闻 会员 周边

使用NetworkStream收取数据不全问题讨论,列举目前方式,求最佳解决方式

0
悬赏园豆:50 [已关闭问题] 关闭于 2012-02-22 08:31

使用NetworkStream收取数据不全问题讨论,列举目前方式,求最佳解决方式

TcpClient tcpClient = new TcpClient();

// 获取流进行读写
//写入预置信息
NetworkStream streamServer = tcpClient.GetStream();
streamServer.Write(PackageContent, 0, PackageContent.Length);

//读取返回数据
……

 

读取返回数据采取以下两种方式,都存在收取不全问题
方式一:

while ((i = streamServer.Read(bytes, 0, bytes.Length)) != 0)
{
for (int j = 0; j < i; j++)
{
list.Add(bytes[j]);
}
}

 

方式二:

do
{
i = streamServer.Read(bytes, 0, bytes.Length);
for (int j = 0; j < i; j++)
{
list.Add(bytes[j]);
}

}
while (streamServer.DataAvailable);

 

以上两种方式理想状态下正常,在客户端和服务器端在单台机器或者局域网部署问题不明显,一般能收全,但是在互联网环境下,比如测试csdn的登陆页面,jquery.js就收不全(自身文件也比较大),原理在于理论上NetworkStream.Read会堵塞进行读,但实际管道为空的时候(出现管道为空的原因推测为网络延迟,服务器端有段时间未返回数据),读出来的数据字节长度为0或者DataAvailable属性为false,导致尚未读取完整就退出了循环。


采用以下方式能一定程度上降低这种影响

streamServer.ReadTimeout = 500; 
do
{
try
{
i = streamServer.Read(bytes, 0, bytes.Length);
for (int j = 0; j < i; j++)
{
list.Add(bytes[j]);
}
}
catch
{

i = 0;
}

}
while (i>0);

 

即给NetworkSteam设置一个读取超时时间,若超时,则认为服务器端已写完,无数据返回,将该值设为100还是读不全csdn登陆页面,设为500就正常了


这种解决方式并不好,会导致服务响应时间变长,求更佳解决方式,此问题为常见问题,欢迎大家讨论,高手赐教。

问题补充:

自己找到一种方法,使用ReadByte,流文件结尾会返回-1,但逐字节读性能太低了,测试wap.baidu.com的新闻模块,基本每次都得6秒的读取时间,有没有更高效的方法?

进一步测试,发现前面速度都很快,就是正常数据全读完后,读末尾的-1,需要5秒多 ,每次都稳定在这个值,具体哪里有问题,如何优化?

大浪淘沙的主页 大浪淘沙 | 初学一级 | 园豆:57
提问于:2012-02-17 10:08
< >
分享
所有回答(3)
0

这种情况产生的原因是,如果读取一端比发送端的读取速度要快,这时候接收端的数据已读完并已经清空了,所以接收端认为这一次通信已完成,但是发送端还在继续发送就产生了读不全的问题,.net的底层存在这种情况,数据读取最好用while循环去读取,不要一次性读取多少个字节,一次性读取多少个字节在某些网络环境不佳的情况下就出现你那种问题了。

使用

while(streamServer.DataAvailable)
{
}
看看,我使用这种读法是可以的。
az235 | 园豆:8483 (大侠五级) | 2012-02-17 10:30

这种方法肯定有问题,你判断DataAvailable就是我上面列举的第二种方式,你没发现问题只是因为没测试出来

支持(0) 反对(0) 大浪淘沙 | 园豆:57 (初学一级) | 2012-02-17 11:06
0

肯定收不全,TcpClient  NetworkStream  是基于流的 ,DataAvailable只能标识缓冲是否有数据可读,DataAvailable在TCP中并不是充当信息边界的,楼主要纠正一下自己的思路。

 

如果读取HTTP,比较简单的方式是使用WEBCLIENT助手类。

如果一定要用TCP,那么需要先行获取文件标头中的文件尺寸后再读取或是按照协议读取,而不是这样没头没闹的读取。

你ReadTimeout 的方法是谁教的!体育老师?太 可怕了,绝不是这样用的

 

LT | 园豆:97 (初学一级) | 2012-02-18 01:04

思路没问题,项目背景必须这样做,自己找到了问题的答案,使用ReadByte,流文件结尾会返回-1,不得不说,微软这个设计的有点……

支持(0) 反对(0) 大浪淘沙 | 园豆:57 (初学一级) | 2012-02-20 11:51
0

服务器端数据发完了,但是客户端收不到结束信号,好好查了一下原因,问题出在ie自动产生的http包头Connection域默认为keep-alive,代理这边收到包后更改为close后就能及时收到服务器端数据发完后给出的结束信号了,这问题解决后就可以很流畅的运行了

大浪淘沙 | 园豆:57 (初学一级) | 2012-02-22 08:30
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册