Java Server – 多个端口?
我即将编程服务器,但我想知道我的想法是否可行。 我的程序将输出到多个端口上的多个客户端 – 每个端口可以被多个客户端访问。
通常我会使用线程套接字服务器,但在这种情况下我需要它为多个端口工作。 我想到的用法是在下面的模糊伪代码中:
- 启动服务器
- 侦听多个端口上的传入连接
- 识别要连接的端口
- 如果是端口1,则启动一个侦听客户端的线程并输出消息类型
x
- 如果是端口2,则启动一个侦听客户端的线程并输出消息类型
y
- 如果是端口1,则启动一个侦听客户端的线程并输出消息类型
希望这有点意义,你可以看到我正在尝试做什么。 简单地说:听取选定的端口,根据连接的端口创建一个线程套接字连接。
这是可行的,还是我要结束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
包来创建一个可以监听的非阻塞异步服务器在多个端口上。
您无法收听所有端口,但您可以收听其中的一组端口。 为要侦听的每个端口创建一个ServerSocket
( http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29 ),并接受每个端口上的连接。
我认为你不能听所有的端口,不。 对于操作系统来说,这将是非常昂贵的,因此根本不是端口监听的工作方式。
如果多个应用程序同时侦听“所有”端口,网络子系统应该向哪个应用程序传送传入数据包怎么办?
这应该可以使用NIO,但是我没有理由避免每个侦听器有一个线程,除非你有超过1K的端口。
你真的需要多个监听端口吗? 在大多数情况下,一个端口应该可以支持所有类型的客户端,并让客户端告诉服务器(或服务器确定需要什么类型的连接)