我正在使用Java NIO用Java编写聊天服务器。服务器接受连接没有问题,但只要select()返回>在第一个客户端之后,即使没有挂起的连接,服务器套接字也始终位于所选的密钥集中。即使select()返回1,所选的键集也将包含2个元素并包含服务器套接字。这会导致accept()返回null。
非常感谢任何帮助。
主循环:
public void start() throws IOException {
Set<SelectionKey> keys;
Iterator<SelectionKey> keyIterator;
this.keepGoing = true;
while (keepGoing) {
int readyChannels = this.selector.select();
if (readyChannels == 0)
{
continue;
}
keys = this.selector.selectedKeys();
keyIterator = keys.iterator();
while (keyIterator.hasNext())
{
SelectionKey currentKey = keyIterator.next();
if (currentKey.isAcceptable())
{
addClient(currentKey);
}
if (currentKey.isReadable())
{
readSock(currentKey);
}
if (currentKey.isWritable())
{
// write data to the buffer and remove OP_WRITE
}
}
}
}
服务器初始化代码:
public Server(int port) {
this.listenPort = port;
try
{
this.selector = Selector.open();
this.listenChannel = ServerSocketChannel.open();
this.listenChannel.socket().bind(new InetSocketAddress(this.listenPort), BACKLOG);
this.listenChannel.configureBlocking(false);
this.listenChannel.register(this.selector, SelectionKey.OP_ACCEPT);
}
catch (IOException e)
{
System.out.println("Server could not initialise: " + e.getMessage());
}
this.users = new HashMap<>();
}
addClient方法:
private void addClient(SelectionKey key) throws IOException {
ServerSocketChannel acceptSocket = (ServerSocketChannel) key.channel();
SocketChannel newClient = acceptSocket.accept();
SelectionKey clientKey;
// Set the new client to non-blocking mode and add to the selector
newClient.configureBlocking(false);
clientKey = newClient.register(this.selector, SelectionKey.OP_READ);
// Add a new key-user pair to the user list
this.users.put(clientKey, new User());
// Attach a buffer for reading the packets
clientKey.attach(new PacketBuffer(newClient));
}
答案 0 :(得分:3)
您必须在keyIterator.next()之后调用keyIterator.remove(),或者在循环结束时清除所选的键集。选择器不会从该组中删除键,这取决于您。但是你还需要注意,accept()可以在非阻塞模式下返回null,并相应地进行防御性编程。