What are some reasons NetworkStream.Read would hang/block?

只愿长相守 提交于 2019-11-26 17:54:40

The Remarks section of the documentation for NetworkStream.Read is misleading. It says:

This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.

It should say:

This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method blocks until data becomes available or the connection is closed. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.

Sometimes there'll be data already in the socket buffer and sometimes there won't, presuambly.

One common reason for seeing a NetworkStream block is if each side of the connection is expecting the other to close. For example, if you make an HTTP 1.1 keep-alive connection, but still do the "read until the connection is closed" way of getting content.

One common mistake while dealing with NetworkStream is sending unfinished commands via Write method which causes a consecutive Read call hanging.

See the below example that tries to send a user name to an opened FTP port. It expects a respond like 331 Please specify the password but the Read method hangs:

var request = Encoding.ASCII.GetBytes("user [username]");
networkStream.Write(request, 0, request.Length);
var streamReader = new StreamReader(networkStream);
var response = streamReader.ReadLine(); // <-- hangs

A magic solution is to replace the first line with the following:

var request = Encoding.ASCII.GetBytes("user [username] \r\n");

By simply adding \r\n phrase at the end of the command, everything will just start to work as expected.

If no data is available for reading, the Read method will block until data is available. Consider using the Async Socket functions if you don't want to block. http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!