【问题标题】:server handling many clients java服务器处理许多客户端java
【发布时间】:2013-04-02 14:56:13
【问题描述】:

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

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 ?
        }

    }

}

【问题讨论】:

    标签: java multiserver


    【解决方案1】:

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

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

    如果您还没有在应用程序中使用过多线程并且对并发了解不多,那么现在是尝试的好时机,阅读Oracle Concurrency Lesson,或者在线查找教程,这里有很多。

    现在,一旦(或如果)您知道线程是如何工作的,请确保您尽可能地分解您的函数并查看哪些函数可以同时发生。我能想到的 Web 服务器示例如下:

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

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

    祝你好运!

    【讨论】:

      【解决方案2】:

      您正在寻找一个线程池服务器。你开始的方式很好。现在您只需实现一个 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)); 如果线程空闲,我会执行请求。否则它会进入线程池的队列。

      您甚至可以将其从 Fixed 更改为其他一些 Threadpool!只需看看 Executors 并采取你需要的东西。 Executors
      希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 1970-01-01
        • 2011-06-26
        • 1970-01-01
        • 1970-01-01
        • 2016-04-09
        • 1970-01-01
        相关资源
        最近更新 更多