Hi All
It seems like the FileChannel.transferFrom(ReadableByteChannel src, long
position, long count) method does not throw the documented / expected
IOExceptions when a remote party closes its side of a connection. The
method instead keeps returning that 0 bytes was read, while internally
it sees a -1 on an attempted read, which it hides at the Java source
code level.
This causes our LengthDelimitedDecoder to fail to detect such truncated
message bodies / connection close events. Interestingly, the
channel.isOpen() always returns true, even when tcpdump and netstat
shows that the remote end of the connection had closed.
I am attaching a small test class which demonstrates this.. I do not
believe it would be possible to change the behavior of the JDK - can we
work around this?
regards
asankha
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class MyTest {
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(9000);
new Thread(new Runnable() {
public void run() {
try {
Socket s = ss.accept();
PrintWriter out = new
PrintWriter(s.getOutputStream(), true);
for (int i=0; i<3; i++) {
out.println("Hello World " + i);
Thread.sleep(1000);
}
s.close();
System.out.println("=> CLOSED socket");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new
InetSocketAddress(InetAddress.getLocalHost(), 9000));
Selector selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT |
SelectionKey.OP_READ);
final FileChannel fileChannel = new RandomAccessFile("/tmp/x",
"rw").getChannel();
long pos = 0;
long count = 0;
while (selector.select() > 0) {
Set keys = selector.selectedKeys();
Iterator it = keys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
SocketChannel myChannel = (SocketChannel) key.channel();
it.remove();
if (key.isConnectable()) {
if (myChannel.isConnectionPending()) {
myChannel.finishConnect();
}
} else if (key.isReadable()) {
count = fileChannel.transferFrom(myChannel, pos, 100);
System.out.println("Transferred : " + count + "
socket open ? : " + myChannel.isOpen() + " connected ? : " +
myChannel.isConnected());
pos += count;
Thread.sleep(1000);
if (count == 0) {
try {
int i = myChannel.read(ByteBuffer.allocate(1));
System.out.println("read : " + i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
--
Asankha C. Perera
AdroitLogic, http://adroitlogic.org
http://esbmagic.blogspot.com
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]