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

学海无涯,行者无疆
全栈领域优质创作者
2012-02-17 09:07:36

TcpClient tcpClient = new TcpClient();

// 获取流进行读写
//写入预置信息
NetworkStream streamServer = tcpClient.GetStream();
streamServer.Write(PackageContent, 0, PackageCo[code=C#]
ntent.Length);

//读取返回数据
……
[/code]

读取返回数据采取以下两种方式,都存在收取不全问题
方式一:
  
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就正常了


这种解决方式并不好,会导致服务响应时间变长,求更佳解决方式。


...全文
144 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
Http的headers下就有Content Length是http包体的长度,我用TcpClient读的是整个包的内容,包括包头和包体,我要做的东西类似一个代理,自己去加开始标志和结束标志不适用
gomoku 2012-02-17
  • 打赏
  • 举报
回复
[Quote=引用楼主 seawaving 的回复:]
...比如测试csdn的登陆页面,jquery.js就收不全(自身文件也比较大),
[/Quote]
比如Http的headers下就有Content Length,告示你内容会有多长。知道内容有多长后就好办了:不断接收直到内容收满或超时。

如果是自己的协议包,同理添加一个类似的长度标志就可以了。

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧