27

これはまだ別のTcpClient対ソケットではありません。

TcpClientは、開発を容易にするためのSocketクラスのラッパーであり、基盤となるSocketも公開します。

まだ ...

TcpClientクラスのMSDNライブラリページで、次のコメントを読むことができます。

TcpClientクラスは、同期ブロッキングモードでネットワークを介してストリームデータを接続、送信、および受信するための簡単なメソッドを提供します。

そして、Socketクラスの場合:

Socketクラスを使用すると、ProtocolType列挙にリストされている通信プロトコルのいずれかを使用して、同期データ転送と非同期データ転送の両方を実行できます。

TcpCientのみを介して一部のデータを非同期で送受信するには、GetStreamを呼び出して、TAPパターンに従ってReadAsyncメソッドとWriteAsyncメソッドを呼び出すことにより、データを非同期で読み取り/書き込みできる基になるNetworkStreamを取得する必要があります。 (潜在的にasync / awaitコンストラクトを使用します)。

ソケットを介して非同期でデータを送受信するには(私は専門家ではありませんが、正しく理解できたと思います)、BeginRead / EndRead BeginWrite / EndWrite(または単にReadAsyncまたはWriteAsync .. TAPパターンを公開しない-つまり、タスクを返さない..混乱する)。

まず、.NET 4.5のSocketクラスがTAPパターンを実装しない理由、つまり、ReadAsyncとWriteAsyncがタスクを返す理由(後方互換性を維持するために別の方法で呼び出された場合のイベント)はありますか?

とにかく、APMモデルのメソッドペアからTaskメソッドを作成するのは簡単なので、この非同期メソッド(読み取り用)をReadAsyncTAP(タスクを返す)と呼んだとしましょう。

Ok ?async Task<Byte[]> ReadNbBytes(int nbBytes)ここで、コードから呼び出してネットワークから特定のバイト数を非同期的に読み取るクライアントメソッドをコーディングするとします。

TcpClientのみに基づくこのメソッドの実装は、GetStreamを呼び出すことによってNetworkStreamを取得し、バッファーがいっぱいになるまでReadAsync呼び出しを待機する非同期ループを含みます。

ソケットに基づくこのメソッドの実装には、バッファーがいっぱいになるまでReadAsyncTAPで待機する非同期ループが含まれます。

結局のところ、クライアントコードの観点からは、違いはないと思います。どちらの場合も、への呼び出しはawait ReadNbBytesすぐに「戻ります」。しかし、それは舞台裏で違いを生むと思います... TcpClientの場合、NetworkStreamに依存しているため、ソケットを直接使用する場合と比較して、読み取りはどの時点でもブロックされるかどうかはわかりませんか?そうでない場合、同期ブロッキングモードについて話しているときにTcpClientに対して行われたコメントは間違っていますか?

誰かが明確にすることができれば大いに感謝されるでしょう!

ありがとう。

4

1 に答える 1

28

ストリームの非同期I/OTcpClientはブロックされません。MSDNのドキュメントが間違っているようです(これは、ReflectorでNetworkStreamの非同期I / O呼び出しに従って確認できます)。

Streamタイプは「興味深い」です。デフォルトでは、Stream基本クラスは同期I/Oでスレッドプールスレッドをブロックすることによって非同期I/Oを実装します。MemoryStreamしたがって、同期メソッドのみを提供するのようなもので非同期I/Oを実行する必要はありません。

NetworkStream 非同期I/Oを提供するため、インスタンスの非同期I/ONetworkStream実際には非同期です。ただし、これが常に当てはまるとは限りません。FileStream特に、通常非同期ではありませんが、インスタンスを適切に構築した場合は非同期になります

SocketTAPメソッドがない理由について:それは非常に良い質問です!見落としだったと思いますが、.NET 4.5がリリースされたので、わざと省略されたようです。APIを過度に複雑にしたくない可能性があります-Socketには、同じ一連の操作(、、、、、、、)をカバーする同期APIと2つの非同期APIすでにあります。TAPは、そのフルセットに対して2つの追加の非同期APIを必要とします。それは少なくとも興味深い命名状況を引き起こします(名前はすでに使用されており、操作ごとにさらに2つの名前が追加されます)。SendSendToReceiveReceiveFromConnectAcceptDisconnect*Async*Async

補足:「追加の」APIは、高性能の非同期Socket通信用です。彼らはを使用しますSocketAsyncEventArgs。これは使いやすさは劣りますが、メモリの無駄が少なくなります。TAP APIがに追加された場合Socket、使いやすいバージョン(wrapping Begin/ End)とより高性能なバージョン(wrapping Async)の両方を提供する必要があります。

のTAPメソッドの作成に興味がある場合はSocket、StephenToubのAwaitingSocket Operations(彼は高性能APIのラッパーのみを提供しています)から始めることをお勧めします。async有効なソケットにも同様のものを使用します。

于 2012-08-16T10:56:51.377 に答える