問題タブ [socketasynceventargs]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
1 に答える
595 参照

.net - SocketAsyncEventArgs フラグメントの順序

SocketAsyncEventArgs を使用した受信ソケット パケットの順序付けに問題があります。私の問題の核心は、クライアントがサーバーにパケットを送信すると、サーバーが非標準サイズのフラグメントでパケットを受信し、それらがランダムな順序で処理されることです。これは明らかに、アプリがパケットをデコードできず、会話全体が台無しになることを意味します。

たとえば、クライアントは Socket.NetworkStream.Write() メソッドを使用して完全なパケットを送信します。

SocketAsyncEventArgs を使用するサーバーは、2 つの個別のパケットで非同期コールバックを受信しますが、パケットの最後のチャンクが最初に処理されます。

これはすべてのパケットで発生するわけではなく、パケット サイズまたはタイミングに基づいて正確に再現することはできませんでした。最後のパケットが正常に受信されたことをサーバーが確認するまで、クライアントが別のパケットを送信しないように、送信/確認通信プロトコルを実装します。

最もイライラする部分は、サーバー上の Socket.Available が常にゼロであることです。これは、ドキュメントによると、何も読み取ることができないことを意味します

ゼロで利用可能で、SocketEventArgs.Count は価値のあるものを何も提供していないようであり、オフセットは実際のデータストリームに基づいた場所ではなく、受信バッファーに関係している必要があります。これらのフラグメントをどのように配置できるかわかりません注文。

問題は、パケットの最初の部分の非同期コールバックが、完全に処理されてから最初の部分に戻る 2 番目のコールバックによってプリエンプトされることだと思います。問題は、コールバック全体を同期できないことです (.NET に Java のような同期機能があればいいのに)。たとえ私がそうしたとしても、そもそも非同期コールバックの利点が無効になるようです。

これらが間違った順序で来る原因、またはそれらを正しく処理するにはどうすればよいですか?

0 投票する
1 に答える
4425 参照

c# - TcpListener と SocketAsyncEventArgs

TcpListenerの代わりに高性能/高スループットTCPサーバーを実装するために使用しない正当な理由はありSocketAsyncEventArgsますか?

私はすでにこの高性能/高スループットのTCPサーバーを実装しましSocketAsyncEventArgsたいくつかの TPL データ フローといくつかの Rx を使用してコードを作成すると、完全に機能します。この取り組みのほぼ教科書です。実際、私はこれらの内容の 80% 以上を他の人のコードから学びました。byteSocketAsyncEventArgs

ただし、いくつかの問題と懸念があります。

  1. 複雑さ: このサーバーに対するいかなる種類の変更も、チームの別のメンバーに委任することはできません。そのため、この種のタスクに縛られ、他のプロジェクトの他の部分に十分な注意を払うことができません。
  2. メモリ使用量(固定byte配列):SocketAsyncEventArgsプールを使用するには、事前に割り当てる必要があります。そのため、100000 の同時接続を処理するために (さらに悪い状況では、異なるポートであっても)、大量の RAM が無用にそこに置かれます。事前に割り当てられます (これらの条件が時々満たされる場合でも、サーバーは毎日 1 つまたは 2 つのそのようなピークを処理できるはずです)。
  3. TcpListener実際にはうまく機能します:私は実際にテストを行いました(バージョンではなく専用スレッドで使用し 、受け入れられた接続をaに送信し、 sをインプレースで作成しないTcpListenerなどのいくつかのトリックを使用)、最新バージョンの. NET とほぼ同じように非常にうまく機能し、データ損失がなく、メモリ フットプリントが少ないため、サーバーで大量の RAM を浪費せず、事前割り当ても必要ありません。AcceptTcpClient asyncConcurrentQueueTaskSocketAsyncEventArgs

では、なぜTcpListenerどこにも使用されていないのに、誰もが (私を含む) を使用しているのSocketAsyncEventArgsでしょうか? 何か不足していますか?

0 投票する
3 に答える
481 参照

.net - SocketAsyncEventArgs の "pooled byte[]" スタイルはメモリ要件の削減に役立ちますか?

プールされたSocketAsyncEventArgsスタイルが、多くの同時接続を提供するサーバーのメモリ消費を削減するのにどのように役立つかわかりません。

はい、前述の MSDN ページでa System.IAsyncResult object be allocated for each asynchronous socket operation.

そして、初期の調査では、何らかの理由で、せいぜい一握りのバイト配列のみを割り当てて、同時に接続されている何千ものクライアント間でそれらを共有できると信じていました。

しかし、何千ものクライアント接続でデータを待ちたい場合はReceiveAsync、毎回異なるバイト配列 (SocketAsyncEventArgs にラップされる) を提供して、何千回も呼び出す必要があるようです。クライアントが送信することを決定する時間。おそらく 10 秒です。

したがって、クライアントがデータを送信する直前に ReceiveAsync を呼び出さない限り (または、その後、いくつかのネットワーク スタック バッファーに依存しますか?)、これはクライアントの裁量であり、サーバーにとって予測不可能です。運が悪く、バイト配列がそこに座って、クライアントがお尻を動かすのをぼんやりと待っています。

私は、単一のバイト配列(または、並列化が理にかなっている場合は、リスニングスレッドごとに単一の配列)を使用して数千の接続をリッスンし、それらの接続のいずれかが何かを送信すると(ネットワークスタックバッファに入る必要があります)とにかく最初に)、その配列にコピーされ、リスナーが呼び出され、リスナーが完了すると、配列を再利用できます。

これは本当に Socket.*Async() メソッドでは不可能ですか?

このようなことは、.net のソケット ライブラリでまったく可能ですか?

0 投票する
0 に答える
75 参照

.net - 複数の SocketAsyncEventArgs 間で送信 byte[] バッファーを共有する

常に同じデータを多くのクライアントに送信するシナリオ、つまり、おそらく PGM などのマルチキャストを使用するように切り替える必要がある (そして将来的に切り替える) シナリオでは、同じ配列を使用することはスレッドセーフでしょうかbyte[]?複数のインスタンスをSocketAsyncEventArgs複数のソケットに渡し、同時にSendAsync送信しますか?

結局のところ、SendAsync はバッファーからのみ読み取る必要があるため、インスタンスの共有は問題になりません。後でそのバッファを再利用できるようにするには、参照カウントを行う必要があり、他にも取り組むべき問題があるかもしれませんが、私の質問は何よりもまずスレッドの安全性についてです。

0 投票する
1 に答える
1941 参照

c# - SocketAsyncEventArgs から継承したクラスに IDisposable インターフェイスを実装する方法

私は C# .NET 4.0 で巨大なプロジェクトに取り組んでいます。System.Net.Socketsから継承されたカスタム クラスがあります。SocketAsyncEventArgsクラス。次のようなもの:

そこで、CleanUp() メソッドの内容を Dispose(bool) メソッドに移動したいと思いました。

最初に、基本クラス SocketAsyncEventArgs のソース コードを確認しました (ソースとしてメタデータが表示されるように [定義へ移動] を使用)。このクラスは IDisposable インターフェイスを実装していることがわかりました。Dispose(bool) メソッドをオーバーライドする必要があるだけですね。(詳細については、MSDN の IDisposable インターフェイス、「IDisposable と継承階層」セクションを参照してください)。私にとって新しいことは何もありません... 残念ながら、SocketAsyncEventArgs クラスは次のように実装されています。

つまり、保護されているのではなくプライベートとして実装されているため、Dispose(bool)メソッドをオーバーライドする方法はありません...この理由は何ですか?

次に、 MSDN のSocketAsyncEventArgs.Dispose()メソッドについて読みました。面白いことに、次のセクションが含まれています。

継承者への注意事項

Disposeは、他のオブジェクトから複数回呼び出すことができます。Dispose(Boolean)をオーバーライドするときは、 Disposeの以前の呼び出しで以前に破棄されたオブジェクトを参照しないように注意してください 。Dispose(Boolean)の実装方法の詳細については、Dispose メソッドの実装を参照してください。

待って…何?

Dispose(Boolean)をオーバーライドすると、...

Dispose(Boolean) をオーバーライドするにはどうすればよいですか?

この場合、IDisposable インターフェイスを実装するための推奨される方法は何ですか?

0 投票する
0 に答える
611 参照

c# - SocketAsyncEventArgs を使用してデータを C# TCP クライアントにプッシュする

リンクに従って、非同期 TCP サーバーを作成しました。ただし、すべての例は、受信への応答としてデータを送信することのみをカバーしています。私の質問は、データを特定の TCP クライアントにプッシュする方法です。

byte[] をクライアント ID 1 に送信/プッシュする必要があるとしましょう。SocketAsyncEventArgs アーキテクチャを使用してこれを達成するにはどうすればよいですか?

アクティブな接続とクライアント ID のリストを保持する必要があることはわかっています。データをプッシュするには、このリストをどのように表示する必要がありますか?