.NET Socket和NetworkStream都提供Read方法,当没有可用数据时,它会阻塞。问题是,如果客户端不知道消息的大小,就没有可靠的方法来理解服务器何时完成发送消息。
我的问题是 - 更高级别的库(如HTTP级WebRequest)使用什么原则来停止从套接字读取并向客户端显示完整的消息,而不诉诸任何类型的读取超时?似乎HTTP协议不提供任何“EOF”令牌......
答案 0 :(得分:3)
HTTP 1.1通过使用两种机制之一来管理它。要么在标头中发送content-length,要么使用chunked transfer encoding。分块转码编码是HTTP 1.1优于HTTP 1.0的一大优势,其中,在没有发送内容长度的情况下,无法可靠地检测到传输结束,导致传输问题与有效载荷的实际结束之间存在歧义。在某些情况下(例如HTTP上的音频流),没有内容长度或其他编码可能表明传输结束,但在这种情况下,它对客户端来说并不重要。
答案 1 :(得分:1)
有一些方法可以检查套接字是否有数据待处理。一种是简单地检查每个套接字的Pending
属性,只有在有数据时才调用Receive。但是,这根本不能很好地扩展,我只建议在单个连接的应用程序中使用它。
Socket.Select函数可以使用套接字的IList,并且在短时间之后,将减少此列表以仅包含具有待处理数据的套接字。然后,您可以安全地呼叫接收,而不会阻止。
另一种首选方法是使用异步套接字API。 (在NetworkStream上呼叫BeginReceive
或BeginRead
)。在这些情况下,调用不会阻塞,您可以在调用后继续执行代码。您将函数作为参数传递,该参数将在套接字上的数据挂起时执行。这是在.NET threadpool中的后台线程中处理的,因此这里涉及并发问题,与前两种方法不同。异步操作在OS中的低级别完成,通过使用中断告诉CPU何时数据在网络上等待,而不是像Select一样重复轮询数据。
答案 2 :(得分:0)
在HTTP中,content-length
HTTP标头定义何时可以关闭套接字。
在TCP中,这是任意的,通常客户端或服务器发送一条特殊消息来通知该连接正在终止。