2

私はこの設定をしたいと思います:

  • サーバー ホスティング TCP ソケット サーバー
  • TCP 経由で接続された複数のクライアント (接続を開いたままにする)

次に、サーバーからクライアントへのメッセージを開始したいと思います。これを行う方法がわかりません。同時に複数のクライアント セッションを行っています。私が読んだテクニックには、サーバーがポートでリッスンしていることが含まれており、クライアントからの通信を受信すると、新しいスレッドを起動してそれを処理および処理し、別のクライアントの次の要求をポートでリッスンすることに戻ります。 .
では、それを利用して、それらのスレッドの 1 つで実行されているクライアントにメッセージを送信するにはどうすればよいでしょうか?

興味がある場合は、私の実際の使用シナリオを以下に示します。最終的な目標は、ファイル システムがサーバーにファイルをアップロードするためのリモート コントロールのようなものです。- 各クライアントには、サーバーに接続するシステム トレイで実行される Java バックグラウンド アプリケーションがあります - サーバーは接続をホストし、通信を開始するための RESTFul Web サービスもホストします - モバイル デバイスは RESTFul Web サービスを介してサーバーに接続し、クライアントのファイル システムに関する情報を要求します。そのため、ドリルダウンしてファイルを見つけ、クリックしてファイルをサーバーにアップロードできます。ここでのアイデアは、モバイル デバイスでオフィスから離れているときに、デスクトップからサーバーにファイルをアップロードする必要があるモバイル ユーザーです。(これはカスタム製品のため、サードパーティのアプリは使用できません_

PS: ここで単純なクライアント サーバー チャット プログラムを見てきました: http://way2java.com/networking/chat-program-two-way-communication/

4

2 に答える 2

0

指定したポートでサーバーを常にリッスンする必要があります。サーバーがそのポートでの着信接続を認識したら、そのクライアントとサーバー間の通信を処理する新しいスレッドを作成する必要がありますが、メイン スレッドは他の着信接続をリッスンし続けます。このようにして、複数のクライアントを 1 つのサーバーに接続できます。そのようです:

private void listen() throws IOException {
    serverSocket = new ServerSocket(port)
    while (GlobalFlags.listening) {
        new ServerThread(serverSocket.accept();
        if (GlobalFlags.exit) {
            serverSocket.close();
            break;
        }
    }
}

GlobalFlags はリスニング プロセスを制御するための変数であり、実際には必要ありません。あなたはしばらくTrueを行い、ただずっと聞き続けることができます.

私のプロジェクトでは、スレッドで実行されているリスナーを持つメイン サーバー コントローラーがあります。コントローラは GlobalFlags を制御しました。グローバルフラグを使用する代わりに、スレッド間通信を行うためのより良い方法があると確信していますが、私にとってはこれが当時最も簡単でした。

ServerThread は、クライアントへの出力の送信とクライアントからの入力の受信を切り替えながら常にループしている必要があります。そのようです:

ServerThread(Socket socket) {
    super("GameServerThread");
    this.socket = socket;
    try {
        this.socket.setTcpNoDelay(true);
    } catch (SocketException e) {
        // Error handling
    }
    this.terminate = false;
}

@Override
public void run() {        
    try {
        out = new PrintWriter(socket.getOutputStream(), true);
        in = new BufferedReader(
             new InputStreamReader(
             socket.getInputStream()));

        String inputLine, outputLine;

        while ((inputLine = in.readLine()) != null) {
                outputLine = processInput(inputLine);
                out.println(outputLine);
                if (terminate) {
                    break;
                }
            }
        }
        out.close();
        in.close();
        socket.close();

    } catch (Exception e) {
        // Error handling, should not use Exception but handle all exceptions by themselves.
}

クライアント側では、同様のループを実行するスレッドがあり、サーバーから入力を受け取り、サーバーに出力を送信します。

この例では、processInput はクライアントの入力を処理するために使用される関数です。サーバーに接続を開始させたい場合は、入力をリッスンする前にサーバーに何かを出力ストリームに送信させ、クライアントに最初にリッスンさせることができます。

私は自分のプロジェクトの 1 つからこの例を抽出しました。 this.socket.setTcpNoDelay(true) はプロセスを高速化するはずです。ここを参照してください: http://www.rgagnon.com/javadetails/java-0294.html

"java.net.Socket.setTcpNoDelay() は、TCP_NODELAY を有効/無効にするために使用され、Nagle のアルゴリズムを無効/有効にします。Nagle のアルゴリズムは、送信されるセグメントの数を最小限に抑えることで帯域幅を節約しようとします。アプリケーションがネットワークの遅延を減らし、パフォーマンスを向上させたい場合, 彼らはNagleのアルゴリズムを無効にすることができます.

java.net.Socket.getTcpNoDelay() を使用して、現在の「TCP_NODELAY」設定を取得します。


したがって、特定のクライアントにメッセージを送信するには、作成時にすべてのスレッドを ArrayList に入れることができるため、現在接続されているすべてのクライアントを追跡できます。別のクラスが送信するメッセージをキュー/変数に入れるまで、processInput メソッドを停止してキュー/変数をポーリングすることができます。したがって、クラスのハンドルを取得する方法は、processInput の実装によって異なります。すべてのスレッドに ID を与えることができ (これは私のプロジェクトで行ったことです)、おそらく processInput メソッドに index=ID の ArrayList をポーリングさせることができます。次に、出力をクライアントに送信するには、変数を index=ID に設定する必要があります。

この方法は個人的にはちょっと不格好に思えますが、他にどのようにすればよいかわかりません。おそらくキューを使用し、processInput に入力をそのキューに書き込んでもらい、別のクラスがそれを読み取ってその応答をキューに入れるのを待ちます。しかし、私は個人的に Java でキューを扱ったことがないので、自分で読んでください。

于 2013-02-19T15:06:43.860 に答える
0

私の知る限り、1) TCP ソケット サーバーをホストするサーバー -- 可能 2) TCP 経由で接続された複数のクライアント -- 可能 3) 次に、サーバーからクライアントへのメッセージを開始したい -- 不可能。クライアントは接続の作成を開始する必要があり、サーバーはデータ パケットをお客様に送信できる場合があります。例: ブラウザで Facebook の Web サイトを開く必要があります。PC には静的 IP アドレスがないため、Facebook サーバーはそのページを自分の PC に送信することを決定できません。 、それならあなたのPCがサーバーであり、Facebookのウェブサイト/サーバーがクライアントとして機能するのと同じくらい良い.

于 2016-10-10T07:29:09.287 に答える