0

I am trying to add a write timeout to a SocketChannel by using a Selector:

public int write(ByteBuffer buf, long timeout, SocketChannel socketChannel, Selector selector) {
    int written = socketChannel.write(buf);
    if (written == 0) {
        SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_WRITE);
        try {
            selector.select(timeout);
            if (Thread.interrupted()) {
                throw new InterruptedIOException();
            }
            written = socketChannel.write(buf);
        } finally {
            selectionKey.cancel();
        }
    }
    return written;
}

The plan is to reuse the selector and de-register it after each timeout. But apparently I get the same selectionKey that was previously cancelled if I call my method twice and it is unable to write at all. This results in a CancelledKeyException when register is called during the second method call. I thought I would get a new selectionKey after the first was cancelled.

So how do I do this? I guess calling selectNow() before the register or after the cancel, in order to clear the cancelled keys will solve it but it seems weird, is there a better way?

Slin
  • 1
  • 3
  • If `written` is zero on the second write, you don't loop, so it is difficult to see how what you describe is possible. Is this the real code? – user207421 Aug 26 '17 at 00:55
  • Thank you for the response! I meant if the method is called twice and all 3 socketChannel.write(buf); attempts result in 0. I will clarify the question. – Slin Aug 28 '17 at 15:34
  • It would be better to clear the OP_WRITE bit of the `interestOps`, rather than cancel the key and re-register. – user207421 Aug 28 '17 at 17:23

0 Answers0