我是 Java NIO 的新手,在阅读了一些教程之后,我尝试自己编写一个简单的 NIO 服务器和客户端。 我的服务器只是做了一件简单的事情,就是从客户端监听并打印到控制台,客户端只连接到服务器并向它发送 3 条消息“Hello”。 问题是我的服务器监听并很好地处理了 3 条消息,之后它应该被阻止并继续监听,但它没有,没有阻止,它在无限循环时运行它。这是我的服务器和客户端:
服务器
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class Server {
public static void main(String args[]) throws Exception {
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new InetSocketAddress(8000));
System.out.println("Server actives at port 8000");
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// print
System.out.println("[ " + keys.size() + " ]");
// 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;
}
// if isReadable = true
// then the server is ready to read
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
// Read byte coming from the client
int BUFFER_SIZE = 1024;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try {
client.read(buffer);
} catch (Exception e) {
// client is no longer active
e.printStackTrace();
}
// Show bytes on the console
buffer.flip();
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
System.out.println("[" + charBuffer.toString() + "]");
}
}
}
}
}
这是我的客户:
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class Client {
public static void main(String args[]) throws Exception {
// Create client SocketChannel
SocketChannel client = SocketChannel.open();
// nonblocking I/O
client.configureBlocking(false);
// Connection to host port 8000
client.connect(new java.net.InetSocketAddress("127.0.0.1", 8000));
// Create selector
Selector selector = Selector.open();
// Record to selector (OP_CONNECT type)
SelectionKey clientKey = client.register(selector,
SelectionKey.OP_CONNECT);
int counter = 0;
boolean chk = true;
// Waiting for the connection
while (selector.select(500) > 0 && chk) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// For each key...
while (i.hasNext() && chk) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// Get the socket channel held by the key
SocketChannel channel = (SocketChannel) key.channel();
// Attempt a connection
if (key.isConnectable()) {
// Connection OK
System.out.println("Server Found");
// Close pendent connections
if (channel.isConnectionPending())
channel.finishConnect();
// Write continuously on the buffer
ByteBuffer buffer = null;
for (;chk;counter++) {
Thread.sleep(1000);
buffer = ByteBuffer.wrap(new String(" Client ").getBytes());
channel.write(buffer);
buffer.clear();
if (counter == 2)
{
chk = false;
client.close();
}
}
}
}
}
}
}
谁能解释我的代码有什么问题? 提前致谢。
最佳答案
您可能正在从已接受的套接字 channel 中获取源源不断的 EOS-s。您忽略了 read()
的结果。您至少必须检查它是否为 -1,如果是,则关闭 channel 。
关于java - 即使没有来自客户端的连接,选择器也会无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9736057/