1

新しい接続を無期限に待機し、それぞれをスレッドで処理する統合サーバーを備えたクライアントを作成しています。

受信したバイト配列を、メイン スレッドのシステム全体で使用可能なメッセージ ハンドラーで処理したいと考えています。ただし、現在、処理は明らかにクライアント スレッドで行われます。

Futures、ExecutorService の submit() を見てきましたが、サーバー内でクライアント接続を作成すると、データがサーバー スレッドに返されます。サーバーをブロックせずに処理するために、そこからメイン スレッド (同期されたパケット ストア内でしょうか?) に戻すにはどうすればよいですか?

私の現在の実装は次のようになります。

    public class Server extends Thread {
    private int port;
    private ExecutorService threadPool;

    public Server(int port) {
        this.port = port;
        // 50 simultaneous connections
        threadPool = Executors.newFixedThreadPool(50);
    }

    public void run() {
        try{
            ServerSocket listener = new ServerSocket(this.port);
            System.out.println("Listening on Port " + this.port);
            Socket connection;

            while(true){
                try {
                    connection = listener.accept();
                    System.out.println("Accepted client " + connection.getInetAddress());
                    connection.setSoTimeout(4000);

                    ClientHandler conn_c= new ClientHandler(connection);
                    threadPool.execute(conn_c);
                } catch (IOException e) {
                    System.out.println("IOException on connection: " + e);
                }
            }
        } catch (IOException e) {
            System.out.println("IOException on socket listen: " + e);
            e.printStackTrace();
            threadPool.shutdown();
        }
    }
}
class ClientHandler implements Runnable {
    private Socket connection;

    ClientHandler(Socket connection) {
        this.connection=connection;
    }

    @Override
    public void run() {
        try {
            // Read data from the InputStream, buffered
            int count;
            byte[] buffer = new byte[8192];

            InputStream is = connection.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            // While there is data in the stream, read it
            while ((count = is.read(buffer)) > 0) {
                out.write(buffer, 0, count);
            }
            is.close();
            out.close();

            System.out.println("Disconnect client " + connection.getInetAddress());
            connection.close();
            // handle the received data
            MessageHandler.handle(out.toByteArray());
        } catch (IOException e) {
            System.out.println("IOException on socket read: " + e);
            e.printStackTrace();
        }
        return;

    }
}

更新:堅牢な方法は、TomTom が提案したもののようです - 代わりに新しい java.nio を使用します。このプロジェクトは使用が制限されており、実験的なものであるため、java.io/java.net で使用する最良の方法を知りたいです :)

4

2 に答える 2

0

それはスケーリングしません。あなたがそれをする理由は何ですか?さらに、大量のメモリを浪費します。ソケットごとにスレッドは必要ありません。より優れたJavaIOライブラリを使用してください。Javaの一部として10年ほど利用できるもののように(NGIO?)。1つのソケットでxスレッドを処理し、データを返すだけです。

于 2010-12-22T07:05:14.793 に答える
0

私のオプションでは、同期オブジェクトを使用してメインスレッドとチャットできます。クライアント接続をプールに追加した後、メインスレッドは受け入れ時にブロックでき、同期オブジェクトは、クライアントがそれを処理した後、処理された接続ソケットを置きますキューに応答し、同期オブジェクトをウェイクアップして、メインスレッドがキューから何かを取得して処理できるようにします。メインスレッドが処理した後、受け入れ時にブロックし、同期オブジェクトで待機します。

基本的に、あなたのアーキテクチャは単純/直接的な方法です。新しい方法は、より多くの同時実行サーバーを取得してパフォーマンスを向上させるために Java nio を使用することです。また、nio は最良の方法ではありません...

于 2010-12-23T09:51:42.787 に答える