Java 多线程服务器 - 每个连接都返回数据。在主线程处理?

发布于 2024-10-09 04:25:11 字数 2639 浏览 0 评论 0原文

我正在编写一个带有集成服务器的客户端,该服务器应该无限期地等待新连接 - 并在线程上处理每个连接。

我想在主线程上的系统范围内可用的消息处理程序中处理接收到的字节数组。然而,目前处理显然是在客户端线程上完成的。

我查看了 ExecutorService 的 Futures、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 一起使用的最佳方法:)

I am writing a client with an integrated server that should wait indefinitely for new connections - and handle each on a Thread.

I want to process the received byte array in a system wide available message handler on the main thread. However, currently the processing is obviously done on the client thread.

I've looked at Futures, submit() of ExecutorService, but as I create my Client-Connections within the Server, the data would be returned to the Server thread. How can I return it from there onto the main thread (in a synchronized packet store maybe?) to process it without blocking the server?

My current implementation looks like this:

    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;

    }
}

Update: The robust way seems to be what TomTom suggested - using the newer java.nio instead. As this project is of limited use and more of an experiment, I'd like to know the best way using it with java.io/java.net :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁客 2024-10-16 04:25:11

在我的选择中,您可以使用同步对象与主线程聊天,在将客户端连接添加到池中之后,主线程可以阻塞在accept和同步对象上,在客户端处理它之后,将处理后的连接套接字放入并响应队列,然后唤醒同步对象,这样主线程就可以从队列中获取并处理它,主线程处理后,在接受处阻塞并在同步对象处等待。

基本上,你的架构是一种简单/直接的方式,新的方式是使用java nio,以获得更多的并发服务器并获得更好的性能,而且nio也不是最好的方式......

In my option, you can use a sync object to chat with the main thread, after your add client connections to the pool, the main thread can block at the accept and the sync object, after you client handle it, put the processed connection socket and response to a queue, and then wakeup the sync object, so the main thread can then get something from the queue and process it, after main thread handle it, block at accept and wait at the sync object.

Basically, your architecture is a simple/direct way, the newly way is use the java nio, to get the more concurrency server and get better performance, also the nio is not the best way...

青萝楚歌 2024-10-16 04:25:11

那我将无法扩展。你这样做有什么理由吗?另外,你浪费了大量的内存——你不需要每个套接字一个线程。使用更好的 Java IO 库。就像作为 Java 的一部分使用了大约 10 年的那样(NGIO?)。它用一个套接字处理 x 个线程,只返回数据。

That iwll not scale. Any reason you do that? Plus you waste tons of memory - you dont need a thread PER SOCKET. Use a better Java IO library. Like the one available as part of Java for like 10 years or so (NGIO?). It handles x threads with one socket, just returning data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文