2

非同期アプローチが何を達成するのかについて、私は少し混乱しています。サーバーが複数の接続を受け入れるようにする方法を調べているときに、これに遭遇しました。Aync が C# で正確に何を行っているかを調べているときに混乱するのは、独自のスレッドではないことがわかるということです。ただし、ロックやストールを回避することもできます。たとえば、次のものがあるとします。

    ConnectionManager()
    {
        listener = new TcpListener(port);
        listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);
    }

    public void acceptConnection(IAsyncResult ar)
    {
        //Do stuff
    }

これは、接続が見つかるとすぐに「acceptConnection」関数を実行しますが、呼び出し元関数を介して実行し続けることを意味しますか? (この場合は範囲​​外です)。これにより、複数のクライアントを受け入れることができるサーバー アプリケーションをどのように作成できますか? サーバー/クライアントの相互作用を管理するために以前にスレッドを操作したことがありますが、この概念にはかなり慣れていません。少し漠然としている場合は、お知らせください。MSDN で複数の例を調べましたが、まだ少し混乱しています。よろしくお願いします!

4

2 に答える 2

3

接続が見つかるとすぐに、「acceptConnection」関数を実行します

はい

その後、呼び出し元関数を介して実行を続けますか?

いいえ。

非同期アプローチは何を達成しますか

正しく実行すると、より少ないリソースで 1 秒あたりのリクエスト数を大幅に増やすことができます。

10 個の TCP ポートで接続を受け入れるサーバーを作成しているとします。

ブロッキング API では、ソケットを受け入れるためだけに 10 個のスレッドを作成する必要があります。スレッドは高価なシステム リソースです。たとえば、すべてのスレッドが独自のスタックを持ち、スレッド間の切り替えにかなりの時間がかかります。クライアントが何らかのソケットに接続している場合、OS は対応するスレッドを起動する必要があります。

非同期 API を使用して、10 個の非同期リクエストを投稿します。クライアントが接続すると、acceptConnection メソッドが CLR スレッド プールのスレッドによって呼び出されます。

後もう一つ。

非同期 I/O 操作が完了するのを待った後、呼び出し元関数の実行を続行する場合は、新しい C# の async/await 構文を検討する必要があります。これにより、それが可能になります。この機能は、Visual Studio 2010 のスタンドアロン ライブラリ「Async CTP」として利用でき、Visual Studio 2012 に含まれています。

于 2012-11-09T00:43:33.463 に答える
2

私は ac# やソケットの第一人者であると公言していませんが、私が理解していることから、上記のコードは最初の接続を受け入れ、それ以降は受け入れません。別の BeginAccept を確立する必要があります。

何かのようなもの:

TcpListener listener = null;

ConnectionManager()
{
    listener = new TcpListener(port);
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);
}

public void acceptConnection(IAsyncResult ar)
{
    // Create async receive data code..

    // Get ready for a new connection
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);

}

そのため、非同期接続に加えて非同期受信データを使用すると、受け入れ接続はすぐに終了し、新しい接続をリッスンするように設定されます。これも再注文できると思います。

ストレートソケット接続(TcpListenerではない)の場合、これは私が使用したものです:

(connectedClient は、受信および送信機能を処理し、接続に関するその他の情報を保持する独自のクラスです)。

int Port = 7777; // or whatever port you want to listen on
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
listenSocket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

listenSocket.Bind(ipLocal);

// create the call back for any client connections...
        listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);

private void OnClientConnection(IAsyncResult asyn)
    {
        if (socketClosed)
        {
            return;
        }

        try
        {
            Socket clientSocket = listenSocket.EndAccept(asyn);

            ConnectedClient connectedClient = new ConnectedClient(clientSocket, this);

            connectedClient.MessageReceived += OnMessageReceived;
            connectedClient.Disconnected += OnDisconnection;
            connectedClient.MessageSent += OnMessageSent;

            connectedClient.StartListening();

            // create the call back for any client connections...
            listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);

        }
        catch (ObjectDisposedException excpt)
        {
            // Deal with this, your code goes here

        }
        catch (Exception excpt)
        {
            // Deal with this, your code goes here
        }

    }

これがあなたが探しているものに答えたことを願っていますか?

于 2012-11-09T00:26:37.757 に答える