【问题标题】:java server: start a new thread for each received packet?java服务器:为每个收到的数据包启动一个新线程?
【发布时间】:2012-08-14 14:20:40
【问题描述】:

我目前正在学习如何用 java 编写一个 tcp 服务器。我正在为新的每个客户端连接(多线程服务器)创建一个新线程。

客户端连接到服务器后,我想将数据从客户端发送到服务器。在服务器端,服务器处于从套接字输入流读取数据的 while 循环中。我现在想问:我应该为每个收到的数据包创建一个新线程吗?

例如,客户端发送字符串“Hello”。服务器是否应该在新线程中处理此数据包以便它可以继续读取,因为我认为如果我不创建新线程,服务器不会继续读取,并且如果客户端在“Hello”数据包之后发送另一个数据包例如“Bye”,服务器可能不会读取它,因为它可能仍在忙于处理“Hello”数据包。

要清楚,我不是在谈论 serversockets 接受方法,我是在谈论来自套接字输入流的数据。

请赐教。

【问题讨论】:

  • 每次服务器从accept() 检索套接字时,它应该分配一个新线程来处理会话。每个连接到服务器的新客户端都会触发服务器从accept 获取Socket。我会推荐你​​谷歌一些例子,例如kieser.net/linux/java_server.html.

标签: java multithreading sockets packet serversocket


【解决方案1】:

如果您的数据包处理任务不是很繁重(可能不是),您不应该这样做。线程将处理一条消息并返回接收新消息。不会丢失任何数据 - 如果没有人从输入流中读取数据,则数据传输将保持不变(在所有缓冲区填满之后)。 每个客户端只保留一个线程,在大多数情况下就足够了。

【讨论】:

  • +1 是的 - 不用担心,(无论如何都使用 TCP)。较低层的 Winsock 缓冲和流控制将确保不会丢失任何内容。除非您花费大量时间处理数据,以致超时的客户端认为服务器已死,否则您会没事的。
  • 好的,谢谢,根据您的回答,我现在将决定是否启动线程,这对我来说似乎是最好的解决方案
  • 是的 - 每个客户端启动一个线程,并从 accept() 传递给它的套接字。这就是“经典”同步服务器设计,其中服务器客户端线程代码可以简单地“内联”编写。肯定有异步设计可以更好地执行/扩展,但不可避免地会更复杂,因为您必须提供自己的状态机。
【解决方案2】:

是的,您必须委托给另一个线程才能拥有响应式服务器。不,不要为每个请求创建一个线程(除非客户端负载是微不足道的),而是使用 thread pool 代替。 示例骨架代码(当然你必须以某种方式跳出循环):

private static final ExecutorService threadPool = Executors.newCachedThreadPool();  

while(true){  

  final Socket clientConnection = serverSocket.accept();  
  threadPool.execute(new Runnable(){  
            public void run(){  
                  processConnection(clientConnection);  
            });               

}  

我应该为每个收到的数据包创建一个新线程吗?

没有。每个线程将处理自己的连接(接收客户端数据包),因此连接客户端将得到更快的服务,因为主侦听器将继续接受连接

【讨论】:

    【解决方案3】:

    每个客户端连接一个线程对于小型应用程序来说很好。但是,每个客户端请求/数据包一个线程根本不是一个好方法。只要确保您的服务器可以及时与客户端通信即可。

    请注意,您创建的线程数不是无限的,这取决于您使用的操作系统。实际应用程序使用线程池来处理此类情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      • 2016-10-18
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      相关资源
      最近更新 更多