我正在尝试允许多个连接到一个小型Java服务器类型的应用程序。它工作正常,但如果一个连接打开然后挂起,所有后续连接将挂起。我不知道如何处理每个连接,在他们自己的线程中最多约20个并发连接,同时跟踪哪个线程属于哪个客户端等。到目前为止我的代码是:
private void init() {
try {
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port
server.socket().bind(new InetSocketAddress(host, port));
System.out.println("Server connected on " + host + ":" + port);
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector, SelectionKey.OP_ACCEPT);
// Infinite server loop
for (;;) {
// Waiting for events
selector.select();
// Get keys
Set keys = selector.selectedKeys();
Iterator i = keys.iterator();
// For each keys...
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// if isAccetable = true
// then a client required a connection
if (key.isAcceptable()) {
// get client socket channel
SocketChannel client = server.accept();
// Non Blocking I/O
client.configureBlocking(false);
// recording to the selector (reading)
client.register(selector, SelectionKey.OP_READ);
continue;
}
// then the server is ready to read
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
// Read byte coming from the client
int BUFFER_SIZE = 32;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try {
client.read(buffer);
} catch (Exception e) {
// client is no longer active
e.printStackTrace();
continue;
}
buffer.flip();
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
Handler dataHandler = new Handler();
client.write(ByteBuffer.wrap(dataHandler.processInput(charBuffer.toString()).getBytes()));
client.socket().close();
continue;
}
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
答案 0 :(得分:4)
每当我需要编写套接字服务器时,我都会避免使用低级JVM类,因为需要处理所有细节。
相反,我使用Apache Mina。这是一个用于编写高性能非阻塞多线程套接字服务器的Java库。
使用Mina的另一个好处是它强制执行clean architecture(IoFilters,协议解码器),这使您的代码更加模块化并使其更易于维护。
答案 1 :(得分:2)
除非您真的想将NIO服务器编写为学习练习,否则我建议您使用Netty。和Mina一样,Peter提到它也是一个用于编写高性能服务器的库。
我最近从使用自己的NIO代码转移到这个库,它使我的代码更加清晰。
答案 2 :(得分:1)
我的解决方案i Netty和Executor创建了ThreadPool。 您只需添加处理程序执行Netty的管道,该管道将执行程序称为ChannelBuffer作为参数。 每个客户端请求都将由单独的线程处理。
查看examples