日期:2014-05-17  浏览次数:21035 次

TcpClient 如何更好的获取全部数据
遇到的问题是:用TcpClient获取网页数据,如果网页数据过大,每次只发送一部分过来,如何判断是否全部接收?
现在使用解决的方法:每次Receive后等待,给服务器第二次发送的时间,然后去判断Available是否还有,如果有再次获取。  缺点:等待很浪费时间资源,而且等待的时间也不好控制,如果网络不好,服务器响应慢,基本不行。

第二种方法:接受到数据后判断是否以</html>结尾,如果不是继续接收。 缺点:接受html网页可以,局限性太大


有没有什么好的方法?HttpWebRequest,HttpWebResponse是如何实现可以全部接收数据的?

------解决方案--------------------
原来LZ是问HttpWebRequest,HttpWebResponse如何完整读取的
其实它们也是建立在socket上,采用Http协议来完成。
引用:
HTTP协议里规定了一份HTTP报文的结束符。
看RFC2616文档4.4节。

4.4 消息的长度(Message Length)
当消息主体出现在消息中时,一条消息的传输长度(transfer-length)是消息主体(messagebody) 的长度;也就是说在实体主体被应用了传输编码(transfer-coding)后。当消息中出现 消息主体时,消息主体的传输长度(transfer-length)由下面(以优先权的顺序)决定::

1。任何不能包含消息主体(message-body)的消息(这种消息如1xx,204和304响应和任 何HEAD方法请求的响应)总是被头域后的第一个空行(CRLF)终止,不管消息里是否存在 实体头域(entity-header fields)。

2。如果Transfer-Encoding头域(见14.41节)出现,并且它的域值是非”“dentity”传输编码 值,那么传输长度(transfer-length)被“块”(chunked)传输编码定义,除非消息因为通过 关闭连接而结束。

3。如果出现Content-Length头域(属于实体头域)(见14.13节),那么它的十进制值(以 字节表示)即代表实体主体长度(entity-length,译注:实体长度其实就是实体主体的长度, 以后把entity-length翻译成实体主体的长度)又代表传输长度(transfer-length)。Content- Length 头域不能包含在消息中,如果实体主体长度(entity-length)和传输长度(transferlength) 两者不相等(也就是说,出现Transfer-Encodind头域)。如果一个消息即存在传输译 码(Transfer-Encoding)头域并且也Content-Length头域,后者会被忽略。

5。通过服务器关闭连接能确定消息的传输长度。(请求端不能通过关闭连接来指明请求消息体 的结束,因为这样可以让服务器没有机会继续给予响应)。

所有的能接收实体的HTTP/1.1应用程序必须能接受"chunked"的传输编码(3.6节),因此当 消息的长度不能被提前确定时,可以利用这种机制来处理消息。

消息不能同时都包括内容长度(Content-Length)头域和非identity传输编码。如果消息包括了 一个非identity的传输编码,内容长度(Content-Length)头域必须被忽略.

当内容长度(Content-Length)头域出现在一个具有消息主体(message-body)的消息里, 它的域值必须精确匹配消息主体里字节数量。HTTP/1.1用户代理(user agents)当接收了一个 无效的长度时必须能通知用户。

附上一个别人用Socket实现的Http协议
要想准确解析,需要详细了解Http协议的规定
一句话,如果TCPClient接收的数据不是Http响应,那么还是要依据双方的传输协议去解析
Availabe只是IP栈缓冲区中还未读取的数据长度,很明显它并不是LZ想要的