2

私はJavaベースのチャットサーバーを書いていますが、現在私のデザインは以下に基づいています:-チャットルームの人がメッセージを送信すると、サーバー側のチャットルームクラスはループ内のすべての参加者に同じメッセージを送信します. ループ内の個々の参加者に対してネットワーク呼び出しが行われているため、これは明らかに不適切な設計です。したがって、たとえば、チャット ルームに 10 人いるとします。1 人のユーザーがメッセージを送信すると、チャットルーム クラスはループ内で同じメッセージを 10 人全員に送信します。たとえば、ループ内の 5 人目の接続が不安定な場合、6 人目から 10 人目がメッセージを見る時間に影響します。

部屋ごとにユニキャストからマルチキャストに移行する場合、チャット ルームごとにプライベート マルチキャスト グループの IP を取得するにはどうすればよいですか? また、チャット ルームごとに個別のグループを用意するのはやり過ぎのようです。主な問題の 1 つは、ループ経由でルーム内のユーザーに返信したときに、ソケット接続を介してデータを送信するメソッドがブロックされていたことです。したがって、非ブロッキング NIO ソケットを使用し、ループ内の受信者にメッセージを送信すると、問題は解決するのでしょうか? ルーム内の受信者へのデータの送信を最適化するために実行できる他の巧妙なトリックはありますか?

4

3 に答える 3

4

簡単な実装は、クライアントごとに 2 つのスレッドを使用することです。1 つのスレッドがソケットから読み取り、もう 1 つのスレッドがソケットに書き込みます。クライアントが少ない場合は、これで問題ありません。多くのクライアントを処理するには、NIO を理解する必要があります。(「多数」は、スレッド化されたモデルがうまく機能しない場合を意味します。)

クライアントの読み取りスレッドは、ソケットからメッセージ全体を読み取り、ChatRoom オブジェクトのキューに入れます。チャット ルームには、メッセージをキューから取り出してクライアントのキューに入れるスレッドがあります。スレッドを書き込んでいるクライアントは、そのキューをポーリングし、メッセージをソケットに書き込みます。

ChatRoom には、接続を受け入れて Client オブジェクトを作成し、それらを Collection に入れるためのスレッドがあります。メッセージ キューをポーリングし、メッセージをクライアント キューに配信する別のスレッドがあります。

Apache Minaには NIO を使用した例があります

于 2009-07-20T04:51:02.127 に答える
2

簡単な方法は、クライアント接続ごとに 2 つのスレッドを使用することです。1 つのスレッドがクライアントからのメッセージの読み取りを処理し、もう 1 つのスレッドがメッセージの送信を処理するため、クライアントから同時にメッセージを送受信できます。

メッセージをブロードキャストするためにクライアント接続をループするときにネットワーク呼び出しを回避するには、サーバー スレッドがクライアントに送信するメッセージをキューに追加する必要があります。java.util.concurrent の LinkedBlockingQueue はこれに最適です。以下に例を示します。

/**
 * Handles outgoing communication with client
 */
public class ClientConnection extends Thread {
    private Queue<String> outgoingMessages = new LinkedBlockingQueue<String>(MAX_OUTGOING);
    // ...
    public void queueOutgoing(String message) {
        if (!outgoingMessages.offer(message)) {
            // Kick slow clients
            kick();
        }
    }

    public void run() {
        // ...
        while (isConnected) {
            List<String> messages = new LinkedList<String>();
            outgoingMessages.drainTo(messages);
            for (String message : messages) {
                send(message);
            }
            // ...
        }
    }
}

public class Server {
    // ...
    public void broadcast(String message) {
        for (ClientConnection client : clients) {
            client.queueOutgoing(message);
        }
    }
}
于 2009-07-20T05:41:03.303 に答える
2

受信者を連続してループするのは悪い考えだということに同意します。このために、ThreadPool を使用して支援することを検討できます。ただし、マルチキャストが最善の策だと思います。チャットルーム モデルに適しています。一度送信するだけで、反復的なアプローチは解決されます。アドレスに別のポートを指定することで、一意のグループ ID を取得できます。

于 2009-07-20T04:51:22.593 に答える