hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Asankha C. Perera" <asan...@apache.org>
Subject Truncated content-length delimited message bodies with sendfile
Date Tue, 19 Feb 2013 11:57:20 GMT
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: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Mime
View raw message