当前位置: 首页 > 面试题库 >

在单独的线程中创建ServerSocket?

卫弘图
2023-03-14
问题内容

ServerSocket在应用程序中使用时遇到问题。

我正在ServerSocket应用程序的构造函数中创建。套接字的构造函数调用该accept()方法以等待客户端连接。

问题在于该accept()方法将冻结我的整个应用程序,直到客户端连接为止。因此,我想问一下是否有替代方法可以ServerSocket在单独的线程中创建整体,在我的主应用程序旁边调用的构造方法ServerSocket及其accept()方法?

编辑:

感谢Olivier的建议,将.accept放入一个可运行的程序并创建一个线程池来处理客户端连接。

那就是我现在的代码:

  public void start(){

      final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

      Runnable serverTask = new Runnable() {
          @Override
          public void run() {

              try {
                  serverSocket = new ServerSocket(port);

                  while (true) {
                      Socket clientSocket = serverSocket.accept();
                      objectout = new ObjectOutputStream(clientSocket.getOutputStream());
                      clientProcessingPool.submit(new ClientTask(clientSocket,objectout)); 
                  }
              } catch (IOException e) {
                  System.err.println("Accept failed.");
              }

          }
      };

一切运行良好!谢谢!


问题答案:

通常,我为此使用N +
1个线程:一个用于ServerSocket,以避免阻塞整个应用程序等待客户端连接;另一个用于服务器套接字。和N个线程来处理客户端的请求,N是线程池的大小(与每个客户端创建新线程相比,我建议使用线程池)。

这是一个示例(只需对其进行编码,您可能希望拥有更好的异常管理等功能,但这只是一个最小的工作示例)

public class Server {

    public static void main(String[] args) {
        new Server().startServer();
    }

    public void startServer() {
        final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

        Runnable serverTask = new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocket serverSocket = new ServerSocket(8000);
                    System.out.println("Waiting for clients to connect...");
                    while (true) {
                        Socket clientSocket = serverSocket.accept();
                        clientProcessingPool.submit(new ClientTask(clientSocket));
                    }
                } catch (IOException e) {
                    System.err.println("Unable to process client request");
                    e.printStackTrace();
                }
            }
        };
        Thread serverThread = new Thread(serverTask);
        serverThread.start();

    }

    private class ClientTask implements Runnable {
        private final Socket clientSocket;

        private ClientTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            System.out.println("Got a client !");

            // Do whatever required to process the client's request

            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}


 类似资料:
  • 问题内容: 许多方法,如,,等已被弃用。 那么使用创建线程有用吗? 问题答案: 在具有数千个线程的大型应用服务器中,使用可能是一种有用的诊断技术。如果您的线程在逻辑上分组在一起,那么当您获得堆栈跟踪时,您可以看到违规线程属于哪个组(例如,“ Tomcat线程”,“ MDB线程”,“线程池X”等),可以是对跟踪和解决问题有很大帮助。

  • 问题内容: 我在处理pyGTK应用程序时遇到一些问题。我给线程一些时间来完成其任务,如果有问题,我还是继续继续,只是警告用户。但是,一旦我继续,该线程就会停止,直到调用gtk.main_quit为止。这让我感到困惑。 相关代码: .................................... 问题答案: 首先,不要继承,使用。 其次,很可能导致您明显的阻塞的原因是它采用了一个默认值为的参

  • 问题内容: 我目前正在开发一个Python应用程序,希望在该应用程序上查看实时统计信息。我想使用它以使其易于使用和理解。 问题是我的Flask服务器应该在我的Python应用程序的最开始处启动,而在最末尾停止。它看起来应该像这样: 因为我需要我的应用程序上下文(用于统计),所以不能使用multiprocessing.Process。然后,我尝试使用threading.Thread,但是Werkze

  • 线程的创建 接下来,我们的第一个目标就是创建一个线程并且让他运行起来。一个线程要开始运行,需要这些准备工作: 建立页表映射,需要包括以下映射空间: 线程所执行的一段指令 线程执行栈 操作系统的部分内存空间 设置起始执行的地址 初始化各种寄存器,比如 sp 可选:设置一些执行参数(例如 argc 和 argv等 ) 思考:为什么线程即便与操作系统无关,也需要在内存中映射操作系统的内存空间呢?Clic

  • 未开设线上课程的老师,可创建并使用独立慕课堂。老师进入中国大学 MOOC平台(www.icourse163.org),登录账号,点击右上角头像的【课程管理后台】: 点击左侧导航的【慕课堂管理】,点击【新建独立慕课堂】: 提示: 1.一个慕课堂加入人数最多为 2000 人; 2.学生加入和 MOOC相关联的慕课堂,系统会自动替学生报名MOOC课程; 3.已做学校云认证的学生,加入无密码的 SPOC

  • 如果我有一个固定大小的线程池,它什么时候真正调用启动线程?(它会在创建时启动它们吗?还是等到我开始提交任务时再启动?)