我正准备编写一个服务器的程序,但我想知道我的想法是否可行。我的程序将在多个端口上输出到多个客户端 - 每个端口可以被多个客户端访问。
通常我会使用一个线程套接字服务器,但在这种情况下,我需要它为多个端口工作。我想到的用法是在下面的一个模糊的伪代码中。
x
y
希望这有一定的意义,你能明白我想做什么。简单的说就是:监听选定的端口,根据连接到哪个端口,创建一个线程socket连接。
这样做是否完全可行,还是说我最终要用多线程的套接字服务器?
编辑:修改了措辞,以更好地反映问题。
对于一个单一实例的 ServerSocket
来监听多个端口。当然,您也可以有多个 ServerSocket
s. 然而,你已经知道。ServerSocket.accept
块。
您可以使用的是 ServerSocketChannel
. 它们的使用方式类似,但不阻塞。
如果没有挂起的连接,当 ServerSocketChannel.accept
调用,那么它就会简单地返回null。
你可以用 Selector
这需要一组通道,并阻止,直到至少有一个有一个挂起的连接。
我不记得如何使用它们的具体细节了,但 这个 似乎是一个不错的代码例子。
编辑: 这是我自己的例子(伪)
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
.
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<SelectionKey> 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语句,但这是为了方便阅读和理解。
记住,这个服务器是以非阻塞异步的方式来设置的,这样你执行的所有IO调用都不会阻塞当前线程。所以 切勿 发起任何新线程 SelectionKey
处理过程。
另外,我知道这并不能完全回答你的问题(可能是,也可能不是),但事实上,它可以让你了解如何使用 java.nio
包来创建一个可以在多个端口上监听的非阻塞异步服务器。
你不能在多个端口监听 都 端口,但你可以监听其中的一组端口。创建一个 ServerSocket
( http:/download.oracle.comjavase6docsapijavanetServerSocket.html#ServerSocket%28int%29。 )为每个你想监听的端口设置一个线程,并在每个端口上接受连接。
这在NIO中应该是可行的,但是我没有看到一个很好的理由来避免每个监听器只有一个线程,除非你有超过1K的端口。
你真的需要多个监听端口吗? 在大多数情况下,应该可以让一个端口支持所有类型的客户端,并让客户端告诉服务器(或由服务器决定需要什么类型的连接)。
我不认为你可以监听所有的端口,不。对操作系统来说,这样做的成本相当高,所以端口监听根本不是这样工作的。
如果多个应用程序同时监听 "所有 "端口,那么网络子系统应该将传入的数据包传送给哪个应用程序呢?