ServerSocket具有多个连接但只有一个线程

时间:2018-06-14 06:22:10

标签: java serversocket

我正在尝试为单线程物理产品编写模拟器。它接受一个长期连接,并且任何其他连接都会收到一条错误消息(在同一个线程中)。

我知道我可以使用带有两个线程的java.net:

  • 线程1 - 在端口XXXX上启动ServerSocket并等待accept()。对于第一个连接,创建一个Socket和Thread#2,并为其他连接产生一条错误消息。
  • 线程2 - 处理套接字IO。

但是我怎么能用一个线程做到这一点,所以它的行为更像物理产品(即重复尝试连接会使线程不能处理第一个连接)?

尝试不使用第三方库,但如果这是唯一的选择,可以这样做。

谢谢!

3 个答案:

答案 0 :(得分:2)

不幸的是,常见的java.net.ServerSocket以及java.nio.channels.ServerSocketChannel只有一种阻止方法来接受传入的连接。但是,java.nio包具有许多其他类和方法,可以通过多路复用打开的通道来处理单个线程中的I / O操作。

此方法仍然会为接受ServerSocketChannel强制执行专用线程,但您可以在单个线程中处理每个接受的连接。

相比之下,ServerSocket方法需要为每个新连接添加一个新线程 Imgaine你使用ServerSocket连接100个客户端,那么你最终会得到101个线程。使用ServerSocketChannel 最终只能使用2个帖子。

仍然编程通常是在复杂性/灵活性和性能之间进行权衡。所以记住这一点。

我能想到的一个可能的解决方案可能是这样的:

public static void main( String[] args ) throws IOException
{
  int portNr = 8080;

  ExecutorService es = Executors.newSingleThreadExecutor();
  ChannelHandler ch = new ChannelHandler(); 
  es.execute( ch );

  // Starting server:
  ServerSocketChannel serv = ServerSocketChannel.open();
  // Bind socket to Port
  serv.socket().bind(new InetSocketAddress(portNr));

  while( serverAlive ) 
  {
    ch.addChannel(serv.accept());
  }
  serv.close();
}

您实际处理新添加的SocketChannel的方式取决于您的应用程序。 ChannelHandler#addChannel方法也是如此。

答案 1 :(得分:0)

您似乎应该接受单一连接,然后关闭ServerSocket。任何未来的连接尝试都将获得连接拒绝。当长期连接结束时,创建一个新的ServerSocket,再接受一个连接,......冲洗并重复。

编辑如果您必须按照下面的评论发送错误消息,则必须接受连接以将其发送,并且如果您必须执行I / O并接受所有操作线程你必须使用java.nio.channels.ServerSocketChannel/SocketChannel,非阻止模式和Selector

答案 2 :(得分:-1)

将ServerSocket与一个线程一起使用根本不是一个好主意。为什么?
你知道socket.accept()等到下一个客户端连接,所以线程被阻塞,如果你只有一个线程,你的整个Programm被阻塞,直到客户端连接。
你可以解释为什么你尝试单线程吗?
如果您有兴趣,我已经编写了一个(免费的,开源的,Creative Commons)API,它也使用AES 128加密数据