入口方法是:
private void writeMessage() {
if (this.socketClosed) {
return;
}
try {
SelectionKey key = getSelectionKey();
if (key != null && !key.isValid()) {
handleFailureToClose(new java.nio.channels.CancelledKeyException());
return;
}
if (key != null && (key.interestOps() & SelectionKey.OP_WRITE) == 0) {
boolean finished = doWrite();
if (!finished)
key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
}
} catch (CancelledKeyException ce) {
logger.error(ce);
handleFailureToClose(ce);
} catch (IOException e) {
logger.error(e);
handleFailureToClose(e);
}
}
对于一次不能写完数据的情况采用了注册写事件的方式。下面这段是selector对于事件的轮询处理代码:
private void flush() {
if (flushingClientConnections.isEmpty())
return;
do {
AbstractClientConnection clientConnection = flushingClientConnections
.poll();
if (clientConnection == null)
break;
try {
boolean flushedAll = flushNow(clientConnection);
if (!flushedAll) {
flushingClientConnections.add(clientConnection);
}
} catch (Exception e) {
logger.error("flush error : {}", e);
}
} while (!flushingClientConnections.isEmpty());
}
private boolean flushNow(AbstractClientConnection clientConnection) {
try {
// Clear OP_WRITE
setInterestedInWrite(clientConnection, false);
boolean finished = clientConnection.doWrite();
if (!finished) {
setInterestedInWrite(clientConnection, true);
return false;
}
} catch (Exception e) {
logger.error("flushNow error : {}", e);
return false;
}
return true;
}
protected void setInterestedInWrite(
AbstractClientConnection clientConnection, boolean isInterested)
throws Exception {
SelectionKey key = clientConnection.getSelectionKey();
if (key == null) {
return;
}
int oldInterestOps = key.interestOps();
int newInterestOps = oldInterestOps;
if (isInterested) {
newInterestOps |= SelectionKey.OP_WRITE;
} else {
newInterestOps &= ~SelectionKey.OP_WRITE;
}
if (oldInterestOps != newInterestOps) {
key.interestOps(newInterestOps);
}
}
注释Clear OP_WRITE的地方已经对于写操作完成的事件,反注册了写事件。