我很好奇为什么代码总是告诉我“密钥不可写”?我的代码有什么用的吗?每次套接字读取内容时,我都会将密钥设置为对OP_WRITE感兴趣,并测试它是否可写。但是,它总是说不可写。我完全是Java套接字编程的新手。
顺便说一句,我不关闭客户。
public final class DateServer {
private DateServer() {
throw new IllegalStateException("Instantiation not allowed");
}
public static void main(final String[] args) throws Exception {
try (final Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open();) {
InetSocketAddress hostAddress = new InetSocketAddress("127.0.0.1", 9999);
serverSocket.bind(hostAddress);
serverSocket.configureBlocking(false);
serverSocket.register(selector, serverSocket.validOps(), null);
while (true) {
int numSelectedKeys = selector.select();
if (numSelectedKeys > 0) {
handleSelectionKeys(selector.selectedKeys(), serverSocket);
}
}
}
}
private static void handleSelectionKeys(Set<SelectionKey> selectionKeys, ServerSocketChannel serverSocket) throws IOException {
Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
while (selectionKeyIterator.hasNext()) {
SelectionKey key = selectionKeyIterator.next();
if (key.isAcceptable()) {
acceptClientSocket(key, serverSocket);
} else if (key.isReadable()) {
readRequest(key);
}
selectionKeyIterator.remove();
}
}
private static void acceptClientSocket(SelectionKey key, ServerSocketChannel serverSocket) throws IOException {
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(key.selector(), SelectionKey.OP_READ);
System.out.println("Accepted connection from client");
}
private static void readRequest(SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = client.read(buffer);
if (bytesRead == -1) {
client.close();
} else {
System.out.println(String.format("Request data: %s", new String(buffer.array())));
int interestOps = 0;
interestOps |= SelectionKey.OP_WRITE;
key.interestOps(interestOps);
if (key.isWritable()){
System.out.println("key is writable");
} else {
System.out.println("key is not writable");
}
interestOps = 0;
interestOps |= SelectionKey.OP_READ;
key.interestOps(interestOps);
}
}
}
答案 0 :(得分:1)
interestOps只告诉选择器下次为选择什么。设置OP_WRITE并不会神奇地为选择键配备预测未来的能力。您必须再次调用select()
以使OP_WRITE实际设置为此代码的结果。
但是您不需要选择器的“权限”来写入频道。你只需写,只有当写入数为零时,你需要担心OP_WRITE,就像这个主题的众多答案一样。
答案 1 :(得分:0)
当您注册客户端时,您只需指定SelectionKey.OP_READ
,因此通道永远无法写入。 (查看Selectionkey.java中的isWritable方法)
public final boolean isWritable() {
return (readyOps() & OP_WRITE) != 0;
}
在您的情况下,OP_WRITE从未注册,因此无效。
使用此功能使其正常工作
client.register(key.selector(), SelectionKey.OP_READ | SelectionKey.OP_WRITE);