Java Server – 多个端口?

我即将编程服务器,但我想知道我的想法是否可行。 我的程序将输出到多个端口上的多个客户端 – 每个端口可以被多个客户端访问。

通常我会使用线程套接字服务器,但在这种情况下我需要它为多个端口工作。 我想到的用法是在下面的模糊伪代码中:

  • 启动服务器
  • 侦听多个端口上的传入连接
  • 识别要连接的端口
    • 如果是端口1,则启动一个侦听客户端的线程并输出消息类型x
    • 如果是端口2,则启动一个侦听客户端的线程并输出消息类型y

希望这有点意义,你可以看到我正在尝试做什么。 简单地说:听取选定的端口,根据连接的端口创建一个线程套接字连接。

这是可行的,还是我要结束multithreading线程套接字服务器?

编辑:更改措辞以更好地反映问题。

我不认为单个ServerSocket实例可以监听多个端口。 您当然可以拥有多个ServerSocket 。 但是,正如您所知, ServerSocket.accept阻止。

您可以使用的是ServerSocketChannel 。 它们以类似的方式使用,但不会阻塞。

如果在调用ServerSocketChannel.accept时没有挂起的连接,则它只返回null。

您可以使用Selector ,该Selector采用一组通道和块,直到至少一个具有挂起连接。

我不记得有关如何使用它们的细节,但这似乎是一个不错的代码示例。

编辑:这是我自己的例子(伪ish)

 Selector selector = Selector.open(); int[] ports = {4000,4001,6000}; for (int port : ports) { ServerSocketChannel server = ServerSocketChannel.open(); server.configureBlocking(false); server.socket().bind(new InetSocketAddress(port)); // we are only interested when accept evens occur on this socket server.register(selector, SelectionKey.OP_ACCEPT); } while (selector.isOpen()) { selector.select(); Set readyKeys = selector.selectedKeys(); Iterator iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); if (key.isAcceptable()) { SocketChannel client = server.accept(); Socket socket = client.socket(); // create new thread to deal with connection (closing both socket and client when done) } } } // tidy up selector and channels 

你好 ,所以让我直截了当。 您要做的是创建一个可以侦听多个端口的服务器,当您获得新连接时,您希望能够告诉该连接使用哪个端口,这是正确的吗? 好吧,如果是这样的话,你可以使用java.nio包很容易地做到这一点。

我们将使用Selector进行准备选择,使用ServerSocketChannel来监听传入的连接。

首先,我们需要声明我们的Selector

 Selector selector = Selector.open(); 

现在让我们创建一个要监听的端口列表并开始监听它们。

 int ports[] = new int[] { 1234, 4321 }; // loop through each port in our list and bind it to a ServerSocketChannel for (int port : ports) { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); serverChannel.socket().bind(new InetSocketAddress(port)); serverChannel.register(selector, SelectionKey.OP_ACCEPT); } 

现在为SelectionKey处理过程。

 while (true) { selector.select(); Iterator selectedKeys = selector.selectedKeys().iterator(); while (selectedKeys.hasNext()) { SelectionKey selectedKey = selectedKeys.next(); if (selectedKey.isAcceptable()) { SocketChannel socketChannel = ((ServerSocketChannel) selectedKey.channel()).accept(); socketChannel.configureBlocking(false); switch (socketChannel.socket().getPort()) { case 1234: // handle connection for the first port (1234) break; case 4321: // handle connection for the secon port (4321) break; } } else if (selectedKey.isReadable()) { // yada yada yada } } } 

也许switch语句对于这样一个简单的任务来说不是必需的,但它是为了便于阅读和理解。

请记住,此服务器是以非阻塞异步方式设置的,因此您执行的所有I / O调用都不会阻止当前线程。 所以不要SelectionKey处理过程中启动任何新线程。

另外,我知道这并没有完全回答你的问题(它可能,它可能没有),但它实际上会让你理解如何使用java.nio包来创建一个可以监听的非阻塞异步服务器在多个端口上。

您无法收听所有端口,但您可以收听其中的一组端口。 为要侦听的每个端口创建一个ServerSockethttp://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29 ),并接受每个端口上的连接。

我认为你不能听所有的端口,不。 对于操作系统来说,这将是非常昂贵的,因此根本不是端口监听的工作方式。

如果多个应用程序同时侦听“所有”端口,网络子系统应该向哪个应用程序传送传入数据包怎么办?

这应该可以使用NIO,但是我没有理由避免每个侦听器有一个线程,除非你有超过1K的端口。

你真的需要多个监听端口吗? 在大多数情况下,一个端口应该可以支持所有类型的客户端,并让客户端告诉服务器(或服务器确定需要什么类型的连接)