9

次の要件を満たすためのベスト プラクティスを探しています。

  • 複数のクライアント ソケットを非同期で処理するフレームワーク
  • 各着信メッセージ プロトコルは、各メッセージがフォーマット文字列であり、改行文字 '\n' で完全にマークされていることを指示します。
  • クライアント側は完全に制御できますが、サーバー側は制御できません。サーバーは、メッセージの完了を示す改行文字を含む文字列ベースのメッセージを受け入れて送信します。
  • 接続された各ソケットを介していつでもメッセージを送信できるようにしたい (各ソケットはメッセージを送受信できる)。
  • 着信メッセージは、コールバックを介して転送する必要があります。
  • 接続されたすべてのソケットからのすべての受信完了メッセージを 1 つのコールバックにルーティングするか、各ソケット クライアントが独自のコールバックを実装するかを実装で選択できるようにしたいと考えています。
  • 最大 4 つのクライアント/ソケットで接続します。そのため、このような限られた数のソケットを活用し、それらすべてを同時に管理できる提案を探しています。

私が使用BeginReceiveEndReceive、実装された IAsyncResult コールバックを使用するフレームワークが、.Net 4.5 をターゲットにしていることを考えると、最先端のものであるかどうか疑問に思います。NetworkStream や他の API の選択肢を使用するなど、より良い解決策はありますか? BeginReceive/EndReceive の実装で本当に困っているのは、EndReceive の後で、BeginReceive を再度呼び出して、コールバックを再度登録する必要があることです。それは私にとってはひどい量のオーバーヘッドのように聞こえます。新しいデータをいつでも非同期に追加できず、同時に別のコンテキストが完全なメッセージを構築し、発生したイベントを介してルーティングできないのはなぜですか?

IAsyncResult を使用する理由は、多くの場合、スレッド処理が処理されるという点で行われますが、次のことに反対するものがあります: NetworkStream を使用し、ストリームから読み書きするだけです。前述のように、文字列メッセージのみが交換され、プロトコルごとの各メッセージは改行文字によって完全にマークされます。別のタスク/スレッドは、 を介して (ネットワーク ストリームに基づいて) ストリームリーダーをポーリングしますReadLine()。これ以上簡単なことはないでしょう?

私が基本的に求めているのは、次のコードを真に非同期にするにはどうすればよいかということです。

public class SocketClient
{
    private TcpClient client;
    private StreamReader reader;
    private StreamWriter writer;

    public event Action<string> MessageCallback;

    public SocketClient(string hostname, int port)
    {
        client = new TcpClient(hostname, port);

        try
        {
            Stream stream = client.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);
            writer.AutoFlush = true;

            //Start Listener on port
            StartListener();
        }
        catch (Exception e)
        {
            throw new Exception(e.ToString());
        }
    }

    public void StartListener()
    {
        Task task = Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    if (MessageCallback != null)
                    {
                        MessageCallback(reader.ReadLine());

                    }

                    //Thread.Sleep(200);
                }
            });
    }

}
4

2 に答える 2

14

現時点では、現在の標準または一般的な慣行はありません。いくつかの選択肢があり、それぞれに長所と短所があります。

  1. TAP メソッドTasksにラップし、 async/を使用しますawait
    • 利点: 実行するのは非常に簡単です。
    • 短所: 低レベルです。async「無限」ループ内でさまざまな操作をすべて自分で管理し、各接続の状態管理を処理する必要があります。
  2. Socket*AsyncメソッドTasksにラップし、 async/を使用しますawait
    • 長所:スピード。これは、最も高速でスケーラブルなオプションです。
    • 短所: 低レベルの「無限」ループと状態管理がまだあり、コードはオプション (1) よりも複雑です。
  3. ソケットの完了をRx イベントに変換します。
    • 利点: 「無限」ループをカプセル化し、完了をイベントのストリームとして扱うことができます。
    • 短所: Rx には多額の学習曲線があり、これは単純な使用例ではありません。各接続の状態の管理は複雑になる可能性があります。
  4. ソケット補完をTPL Dataflowに変換します。
    • 利点: (Rx と同じ): ループをカプセル化し、データのストリームを取得します。
    • 短所: 学習曲線は Rx よりも簡単ですが、接続ごとに複雑な状態管理が必要です。
  5. EAPソケット クラス を提供するNito.Asyncライブラリなどの既存のライブラリを使用します。
    • 利点: 非常に使いやすい。すべてがイベントであり、マルチスレッドの問題はありません。また、状態管理の巧妙な部分はあなたのために行われます。
    • 短所: 下位レベルのソリューションほど拡張性がありません。

あなたの状況 (100 個未満のソケットで 1 秒あたり数百メッセージ) では、私の Nito.Async ライブラリを使用することをお勧めします。これは、これらのオプションの中で最も簡単に機能するオプションです。

プロトコルに関しては、\n手動で s を解析し、独自のバッファリングを行う必要があります。(これは上記のすべての選択肢に当てはまります)。

于 2013-02-25T17:30:23.037 に答える
1

私の推奨に従って、「XXXSend」(XXX はandXXXReceiveの略) の新しい非同期形式を使用してください。利用可能な新しいメソッドは、 SocketAsyncEventArgsを使用してソケットおよびコールバック イベント ハンドラーに関するその他の情報を渡すReceiveAsyncおよびSendAsyncメソッドです。BeginEnd

私はmsdnアーカイブでソケットクライアントとサーバーの良い動作例を見てきました.500接続まで拡張可能でした(私はそれからのプロジェクト適応の1つでテストしたように)が、現在グーグルからそのリンクを見つけることができません..しかしここうまくいけば、同じトピックに関するmsdnアーカイブからの別のリンクです - Get Closer to the Wire with High-Performance Sockets in .NET ..

アップデート

まず第一に、最終的な実装のアイデアと、可能であればいくつかの短いサンプル コード スニペットを提供することしかできません。わかりました、ここで詳細を説明します

最後の段落のリンクにジャンプできると思います。;)

強調したいので、一度強調させてください。イベントベースの非同期パターン (EAP) とは言いません SendAsyncでしReceiveAsyncた。BeginReceive/EndReceiveBeginSend/EndSend

Async 形式の Socket メソッドを使用する利点は、BeginSend/EndSend メソッドよりも高速なソケット プログラミングへの例外のないアプローチであることです。

これは、最大 500 の PARALLEL 接続で役立つことがわかったサンプルのリンクです - Networking Samples for .NET v4.0

.NET 4.5 の await/async 機能を使用する必要があるためです。これは、実装にもWebSocket適応できるクラスの使用法を示す.NET 4.5コードスニペットです-WebSocketsプロトコルのサポート(WebSocketはSocketになると思います)SocketAspNetWebSocketContextSocketAsyncEventArgs

MSDN - Parallel Programming team blogのAwaiting Socket Operationsサンプル コードを見つけました。これは、.NET 4.5 フレームワークから await/async を実装するために使用すると便利です。

これがお役に立てば幸いです。

于 2013-02-25T05:54:51.863 に答える