10

MSDN のドキュメントは、NetworkStream.Read が常にすぐに返されることを示唆しているようです。データが見つからない場合は 0 が返されます。ただし、現在展開されているコードがいくつかありますが、そのコードは一部のケース (まだどのケースかはわかりません) でのみ、NetworkStream.Read がハングしているように見えます。これは、ダンプファイルから収集できたスタックトレースです

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)

NetworkStrea.Read が実際に Socket.Receive を呼び出していることに気付きましたが、これは私が理解している限りブロックされている可能性があります。なぜ時々ブロックされ、時々ブロックされないのかわかりません。

4

4 に答える 4

30

NetworkStream.Readのドキュメントの備考セクションは誤解を招くものです。それは言います:

このメソッドは、データを buffer パラメーターに読み取り、正常に読み取られたバイト数を返します。読み取りに使用できるデータがない場合、Read メソッドは 0 を返します。Read操作は、size パラメーターで指定されたバイト数まで、使用可能なデータをすべて読み取ります。リモート ホストが接続をシャットダウンし、使用可能なすべてのデータが受信された場合、Read メソッドはすぐに完了し、0 バイトを返します。

それは言うべきです:

このメソッドは、データを buffer パラメーターに読み取り、正常に読み取られたバイト数を返します。読み取り可能なデータがない場合、Read メソッドは、データが使用可能になるか、接続が閉じられるまでブロックされます。Read オペレーションは、size パラメーターで指定されたバイト数まで、使用可能なデータをすべて読み取ります。リモート ホストが接続をシャットダウンし、使用可能なすべてのデータが受信された場合、Read メソッドはすぐに完了し、0 バイトを返します。

于 2011-08-05T14:54:29.563 に答える
7

場合によっては、ソケット バッファーに既にデータが存在する場合もあれば、そうでない場合もあります。

ブロックが表示される一般的な理由の 1 つNetworkStreamは、接続の両側で他方が閉じることを期待している場合です。たとえば、HTTP 1.1 の keep-alive 接続を確立しても、「接続が閉じられるまで読み取る」方法でコンテンツを取得する場合です。

于 2011-08-05T14:54:31.980 に答える
5

処理中のよくある間違いの 1 つは、メソッドをNetworkStream介して未完了のコマンドを送信Writeし、連続したRead通話がハングすることです。

開いている FTP ポートにユーザー名を送信しようとする以下の例を参照してください。331 Please specify the password のような応答が必要ですが、Readメソッドがハングします。

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

魔法の解決策は、最初の行を次のように置き換えることです。

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

コマンドの最後に\r\n句を追加するだけで、すべてが期待どおりに機能し始めます。

于 2015-10-13T10:38:48.403 に答える
0

読み取りに使用できるデータがない場合、データが使用可能になるまで Read メソッドはブロックされます。ブロックしたくない場合は、Async Socket 関数の使用を検討してください。 http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx

于 2011-08-05T15:00:53.233 に答える