服务器处理许多客户端java

时间:2013-04-10 16:28:36

标签: java multiserver

家伙!我写了简单的服务器客户端(udp)应用程序。现在我正在尝试使服务器接受许多客户端。据我所知,我需要创建接受和处理客户端的功能,但我对应用程序结构感到困惑。你可以检查我的应用程序是否有正确的骨架? Mayb你可以给我一些提示或例子。所有建议赞赏! :)

class MultiServer {

    private DatagramSocket serversocket;

    public MultiServer() {
        try {
            this.serversocket = new DatagramSocket(6789);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void start() throws IOException {
        while(true) {
            DatagramSocket serversock = serversocket.accept();
            new Thread(new ClientHandler(serversock)).start();
        }
    }

    public static void main(String[] args) {
        Server1 server = new Server1();
        try {
            server.start();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

class ClientHandler implements Runnable {

        private final DatagramSocket clientsocket;

        ClientHandler(DatagramSocket sock) {
            this.clientsocket = sock;
        }

        @Override
        public void run() {
            //receive packet, send msg, get ip, get portnumber ?
        }

    }

}

2 个答案:

答案 0 :(得分:1)

您希望您的服务器能够同时处理多个请求吗?好,这是大多数网络服务器的工作方式。您必须了解多线程和并发的基本概念。

一个简单的服务器一次只能处理一件事。如果在服务器处理其他事情时收到另一个请求会发生什么?没什么,所以应用程序效率不高,根本不可扩展。

如果你还没有在你的应用程序中使用多个线程并且对并发性知之甚少,那么现在是开始使用,阅读Oracle Concurrency Lesson或在线查找教程的好时机。

现在,一旦(或者​​如果)你知道线程是如何工作的,请确保尽可能地分解你的功能,看看可以同时发生什么功能。我能想到的Web服务器的一个例子是:

  • 一个单独的线程,用于侦听端口上的请求。收到请求后,将其放入“请求池”并将其排队以进行处理
  • 处理请求的单独线程(或多个线程/线程池)

您的结构看起来像是在同一个Runnable中接收和处理。无论如何,这只是一个想法,你必须看到什么更适用于你的应用程序。另外,看看新版Java提供的并发工具,Java 6和7提供了许多非常有效的工具(但在我看来也很难理解和使用)。

祝你好运!

答案 1 :(得分:0)

您正在寻找一个Threadpooled Server。你开始的方式很好。现在,您只需实现Java执行服务来处理请求。线程池有一个固定的线程。它确实接受了您的请求并将它们放入队列中,如果请求完成,它将接受下一个请求。因此,您通常不会丢失任何请求。

这是我做的一个小例子:

public class PoolServer implements Runnable {
    private static final int DEFAULT_PORT = 8080;
    private static final String CONFIG = "config.xml";
    protected ServerSocket serverSocket = null;
    protected boolean isStopped = false;
    protected Thread runningThread = null;
    protected ExecutorService threadPool = Executors.newFixedThreadPool(100);
    protected int serverPort;

    public PoolServer() {
        // getting the port from the XML
        this.serverPort = getPortFromXML();
    }

    public void run() {
        synchronized (this) {
            this.runningThread = Thread.currentThread();
        }
        openServerSocket();
        // accepting loop
        while (!isStopped()) {
            Socket clientSocket = null;
            try {
                // accept the client
                clientSocket = this.serverSocket.accept();
                clientSocket.setSoTimeout(2000);

            } catch (IOException e) {
                if (isStopped()) {
                    return;
                }
                throw new RuntimeException("Error accepting client connection",
                        e);
            }
            this.threadPool.execute(new ThreadHandler(clientSocket));
        }
        // loop end
        // server stopped shut down the ThreadPool
        this.threadPool.shutdown();
    }

    private synchronized boolean isStopped() {
        return this.isStopped;
    }

    public synchronized void stop() {
        this.isStopped = true;
        try {
            this.serverSocket.close();
        } catch (IOException e) {
            throw new RuntimeException("Error closing server", e);
        }
    }

    private void openServerSocket() {
        try {
            this.serverSocket = new ServerSocket(this.serverPort);
        } catch (IOException e) {
            throw new RuntimeException("Cannot open port " + this.serverPort, e);
        }
    }

此时this.threadPool.execute(new ThreadHandler(clientSocket));如果线程空闲,我会执行请求。否则它进入Threadpool的队列。

您甚至可以将它从固定更改为其他一些Threadpool!只需看一看执行人员并拿走你需要的东西。 Executors
希望这有帮助!