Java Server - Multiple ports?
It's not possible to for a single instance of ServerSocket
to listen to multiple ports. You can of course have multiple ServerSocket
s. However, as you already know, ServerSocket.accept
blocks.
What you can use instead is a ServerSocketChannel
. They're used in a similar way, but do not block.
If there are no pending connections when ServerSocketChannel.accept
is called then it simply returns null.
You can use with a Selector
which takes a set of channels and blocks until at least one has a pending connection.
I don't remember the specifics on how to use them, but this seems to be a decent code example.
edit: Here is my own example (pseudo-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
Hello, so let me get this straight. What you want to do is to create a server that can listen on multiple ports and when you get a new connection, you want to be able to tell which port that connection used, is this correct? Well if that's the case, you can do this very easily with use of the java.nio
package.
We're going to use a Selector for readiness selection and a ServerSocketChannel to listen for incoming connectings.
First we need to declare our Selector
.
Selector selector = Selector.open();
Now lets create a list of ports to listen on and start listening on them.
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);
}
Now for the SelectionKey
handling process.
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
}
}
}
Perhaps a switch statement is not necessary for such a simple task, but it's for ease of reading and understanding.
Remember, this server is set up in a non-blocking asynchronous way so that all the I/O calls you perform will not block the current thread. So DO NOT initiate any new threads in the SelectionKey
handling process.
Also, I know that this doesn't completely answer your question (it might, it might not) but it will in fact give you an understanding on how to use the java.nio
package to create a non-blocking asynchronous server that can listen on multiple ports.