MSDN documentation seems to suggest that NetworkStream.Read will always return immediately. If no data is found it returns 0. However, I have some code tha开发者_如何学Ct is currently deployed, that only in some cases (and I haven't figured out which ones yet), NetworkStream.Read appears to hang. Here is the stack trace which i was able to gather from a dump file
00000000705ae850 000007fef784f60d DomainBoundILStubClass.IL_STUB(IntPtr, Byte*, Int32, System.Net.Sockets.SocketFlags) 00000000705ae930 000007fef785c930 System.Net.Sockets.Socket.Receive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.Sockets.SocketError ByRef) 00000000705ae9b0 000007ff004eb668 System.Net.Sockets.NetworkStream.Read(Byte[], Int32, Int32) 00000000705aea40 000007fef784e6ae MySocketStuff.SocketConnectCallback(System.IAsyncResult) 00000000705aeb20 000007fef84f2bbb System.Net.LazyAsyncResult.Complete(IntPtr) 00000000705aeb90 000007fef7853c7b System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 00000000705aebe0 000007fef784e5d3 System.Net.ContextAwareResult.Complete(IntPtr) 00000000705aec40 000007fef7d027f9 System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr) 00000000705aeca0 000007fef8b9815e System.Net.Sockets.Socket.ConnectCallback() 00000000705aed20 000007fef93e14c2 System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)
I notice that the NetworkStrea.Read actually calls Socket.Receive which can be blocking as far as I understand. I just don't know why sometimes it would block and sometimes it would not.
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
精彩评论