我遇到了一个问题,我的客户端(SocketChannel)没有注册OP_READ。 ServerSocketChannel之间的连接工作,当我将兴趣设置为OP_WRITE时,Selector按预期处理通道,但当我将其设置为OP_READ时,Selector.selectedKeys为空。
class ClientThread extends Thread {
private static final String TAG = "ClientThread";
/* Wait timeout (milliseconds) */
private static final int TIMEOUT = 3000;
/* The host to connect to */
private InetAddress hostAddress;
/* The port to listen on */
private int port;
/* The selector we'll be monitoring */
private Selector selector;
/* SocketChannel we will be listening on */
private SocketChannel socketChannel;
/* Run check to see if we should quit operations. */
private volatile boolean quit;
/* Buffer to read on */
private ByteBuffer readBuffer = ByteBuffer.allocate(BUF_SIZE);
public ClientThread(InetAddress hostAddress, int port)
throws IOException {
this.hostAddress = hostAddress;
this.port = port;
}
/**
* Quit all pending operations on this thread.
*
* <p>See:
* https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
*/
void quit() {
this.quit = true;
interrupt();
}
public void run() {
// We want a background thread.
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
try {
// Create a non-blocking socket channel
socketChannel = SocketChannel.open();
selector = Selector.open();
socketChannel.configureBlocking(false);
// Kick off connection establishment
socketChannel.connect(new InetSocketAddress(this.hostAddress, this.port));
// Register Selector
socketChannel.register(selector, SelectionKey.OP_CONNECT);
Log.v(TAG, "SocketChannel connected");
while (true) {
// Check if the thread needs to be killed.
if (quit) {
selector.close();
socketChannel.close();
selector = null;
socketChannel = null;
return;
}
// Wait for a channel to be ready.
// Wait for a channel to be ready.
if (selector.select(TIMEOUT) == 0) { // returns # of ready chans
Log.v(TAG, "waiting for connection");
continue;
}
Log.v(TAG, "SocketChannel ready");
// Iterate over the set of keys for which events are available
Iterator selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
Log.v(TAG, "SelectionKey: " + SelectionKeyUtil.readableSelectionKey(key));
if (!key.isValid()) {
Log.v(TAG, "key isInvalid");
continue;
}
// Check what event is available and deal with it
if (key.isConnectable()) {
this.handleConnection(key);
} else if (key.isReadable()) {
this.handleRead(key);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
socketChannel = null;
selector = null;
hostAddress = null;
}
}
public void handleConnection(SelectionKey key) throws IOException {
// Finish the connection. If the connection operation failed an IOException will occur.
SocketChannel socketChannel = (SocketChannel) key.channel();
try {
boolean connected = socketChannel.finishConnect();
Log.v(TAG, "SocketChannel connection finished: " + connected);
} catch (IOException e) {
// Cancel the channel's registration with the selector.
e.printStackTrace();
key.cancel();
return;
}
// Register an interest in reading on this channel
SelectionKey key = socketChannel.keyFor(selector);
key.interestOps(SelectionKey.OP_READ);
}
public void handleRead(SelectionKey key) throws IOException {
// Client socket channel has pending data.
socketChannel = (SocketChannel) key.channel();
readBuffer.clear(); // Prepare buffer for input, ignoring existing state
long bytesRead = socketChannel.read(readBuffer);
if (bytesRead == -1) { // Client maybe closed
socketChannel.close();
} else if (bytesRead > 0) {
Log.v(TAG, "Read bytes available");
}
}
}
任何帮助都会很棒。