You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2005/04/25 20:40:55 UTC

svn commit: r164621 - in /jakarta/httpclient/trunk/http-common/src: examples/org/apache/http/examples/ java/org/apache/http/impl/ test/org/apache/http/mockup/

Author: olegk
Date: Mon Apr 25 11:40:54 2005
New Revision: 164621

URL: http://svn.apache.org/viewcvs?rev=164621&view=rev
Log:
Socket read timeout implementation based on NIO 

Modified:
    jakarta/httpclient/trunk/http-common/src/examples/org/apache/http/examples/ElementalHttpEchoServer.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/AbstractHttpConnection.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultHttpServerConnection.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataReceiver.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataTransmitter.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataReceiver.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataTransmitter.java
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataReceiverMockup.java
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataTransmitterMockup.java

Modified: jakarta/httpclient/trunk/http-common/src/examples/org/apache/http/examples/ElementalHttpEchoServer.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/examples/org/apache/http/examples/ElementalHttpEchoServer.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/examples/org/apache/http/examples/ElementalHttpEchoServer.java (original)
+++ jakarta/httpclient/trunk/http-common/src/examples/org/apache/http/examples/ElementalHttpEchoServer.java Mon Apr 25 11:40:54 2005
@@ -199,7 +199,7 @@
             super();
             this.conn = conn;
             this.params = new DefaultHttpParams(null);
-            new HttpConnectionParams(this.params).setSoTimeout(15000); 
+            new HttpConnectionParams(this.params).setSoTimeout(5000); 
             this.handler = new RequestHandler();
         }
         
@@ -221,7 +221,6 @@
             while (!Thread.interrupted()) {
                 BasicHttpResponse response = new BasicHttpResponse();
                 try {
-                    this.conn.setSocketTimeout(100);
                     HttpRequest request = this.conn.receiveRequest(this.params);
                     System.out.println("Request received");
                     this.handler.handleRequest(request, response);

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/AbstractHttpConnection.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/AbstractHttpConnection.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/AbstractHttpConnection.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/AbstractHttpConnection.java Mon Apr 25 11:40:54 2005
@@ -106,15 +106,17 @@
     }
     
     public void close() throws IOException {
-        HttpDataTransmitter tmp1 = this.datatransmitter;
-        if (tmp1 != null) {
-            tmp1.flush();
+        HttpDataTransmitter tmptransmitter = this.datatransmitter;
+        if (tmptransmitter != null) {
+            tmptransmitter.flush();
         }
         this.datareceiver = null;
         this.datatransmitter = null;
-        Socket tmp2 = this.socket;
-        if (tmp2 != null) {
-            tmp2.close();
+        Socket tmpsocket = this.socket;
+        if (tmpsocket != null) {
+            tmpsocket.shutdownOutput();
+            tmpsocket.shutdownInput();
+            tmpsocket.close();
         }
         this.socket = null;
     }

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultHttpServerConnection.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultHttpServerConnection.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultHttpServerConnection.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultHttpServerConnection.java Mon Apr 25 11:40:54 2005
@@ -219,6 +219,6 @@
             ((ChunkedOutputStream) outstream).finish();
         }
         outstream.flush();
-    }  
-    
+    }
+        
 }

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataReceiver.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataReceiver.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataReceiver.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataReceiver.java Mon Apr 25 11:40:54 2005
@@ -32,7 +32,6 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
-import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
@@ -56,23 +55,16 @@
     private static final int CR = 13;
     private static final int LF = 10;
     
-    private ReadableByteChannel channel = null;
     private ByteBuffer buffer = null;
     
     private Charset charset = null;
     
-    protected void init(final ReadableByteChannel channel, int buffersize) {
-        if (channel == null) {
-            throw new IllegalArgumentException("Channel may not be null");
-        }
-        this.channel = channel;
-        
+    protected void initBuffer(int buffersize) {
         if ((buffersize > 2048) || (buffersize <= 0)) {
             buffersize = 2048;
         }
         this.buffer = ByteBuffer.allocateDirect(buffersize);
         this.buffer.flip();
-        
         this.charset = Charset.forName("US-ASCII");
     }
 
@@ -88,9 +80,11 @@
         return chardecoder;
     }
     
+    protected abstract int readFromChannel(ByteBuffer dst) throws IOException;
+    
     protected int fillBuffer() throws IOException {
         this.buffer.compact();
-        int i = this.channel.read(this.buffer);
+        int i = readFromChannel(this.buffer);
         this.buffer.flip();
         return i;
     }
@@ -222,9 +216,5 @@
         }
         return line.toString();
     }
-    
-    public boolean isDataAvailable(int timeout) throws IOException {
-        return this.channel.isOpen();
-    }    
     
 }

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataTransmitter.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataTransmitter.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataTransmitter.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOHttpDataTransmitter.java Mon Apr 25 11:40:54 2005
@@ -32,7 +32,6 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
-import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
@@ -57,17 +56,11 @@
     private static final int LF = 10;
     private static final byte[] CRLF = new byte[] {CR, LF};
 
-    private WritableByteChannel channel = null;
     private ByteBuffer buffer = null;
 
     private Charset charset = null;
 
-    protected void init(final WritableByteChannel channel, int buffersize) {
-        if (channel == null) {
-            throw new IllegalArgumentException("Channel may not be null");
-        }
-        this.channel = channel;
-        
+    protected void initBuffer(int buffersize) {
         if ((buffersize > 2048) || (buffersize <= 0)) {
             buffersize = 2048;
         }
@@ -80,16 +73,18 @@
         this.charset = Charset.forName(protocolParams.getHttpElementCharset()); 
     }
 
+    protected abstract void writeToChannel(ByteBuffer src) throws IOException;
+    
     protected void flushBuffer() throws IOException {
         this.buffer.flip();
-        this.channel.write(this.buffer);
+        writeToChannel(this.buffer);
         this.buffer.compact();
     }
     
     public void flush() throws IOException {
         this.buffer.flip();
         while (this.buffer.hasRemaining()) {
-            this.channel.write(this.buffer);
+            writeToChannel(this.buffer);
         }
         this.buffer.clear();
     }

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataReceiver.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataReceiver.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataReceiver.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataReceiver.java Mon Apr 25 11:40:54 2005
@@ -31,8 +31,14 @@
 
 import java.io.IOException;
 import java.net.Socket;
-import java.net.SocketException;
 import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
 
 /**
  * <p>
@@ -45,9 +51,12 @@
  */
 public class NIOSocketHttpDataReceiver extends NIOHttpDataReceiver {
 
-    private final Socket socket;
+    private final SocketChannel channel;
+    private final Selector selector;
+    
+    private long readTimeout = 0;
     
-    protected NIOSocketHttpDataReceiver(final Socket socket) throws SocketException {
+    protected NIOSocketHttpDataReceiver(final Socket socket) throws IOException {
         super();
         if (socket == null) {
             throw new IllegalArgumentException("Socket may not be null");
@@ -55,26 +64,37 @@
         if (socket.getChannel() == null) {
             throw new IllegalArgumentException("Socket does not implement NIO channel");
         }
-        init(socket.getChannel(), socket.getReceiveBufferSize());
-        this.socket = socket;
+        this.channel = socket.getChannel();
+        this.channel.configureBlocking(false);
+        this.selector = Selector.open();
+        this.channel.register(this.selector, SelectionKey.OP_READ);
+        initBuffer(socket.getReceiveBufferSize());
     }
     
+    public void reset(final HttpParams params) {
+        HttpConnectionParams connParams = new HttpConnectionParams(params);
+        this.readTimeout = connParams.getSoTimeout();
+        super.reset(params); 
+    }
+
+    protected int readFromChannel(final ByteBuffer dst) throws IOException {
+        if (dst == null) {
+            throw new IllegalArgumentException("Byte buffer may not be null");
+        }
+        this.selector.select(this.readTimeout);
+        int result = this.channel.read(dst);
+        if (result == 0) {
+            throw new SocketTimeoutException("Socket read timeout after " 
+                    + this.readTimeout + " ms");
+        }
+        return result;
+    }
+  
     public boolean isDataAvailable(int timeout) throws IOException {
         if (hasDataInBuffer()) {
             return true;
         } else {
-            boolean result = false;
-            int oldtimeout = this.socket.getSoTimeout();
-            try {
-                this.socket.setSoTimeout(timeout);
-                fillBuffer();
-                result = true;
-            } catch (SocketTimeoutException e) {
-                // no data available
-            } finally {
-                socket.setSoTimeout(oldtimeout);
-            }
-            return result;
+            return this.selector.select(timeout) > 0;
         }
     }    
         

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataTransmitter.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataTransmitter.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataTransmitter.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/NIOSocketHttpDataTransmitter.java Mon Apr 25 11:40:54 2005
@@ -29,8 +29,11 @@
 
 package org.apache.http.impl;
 
+import java.io.IOException;
 import java.net.Socket;
 import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
 
 /**
  * <p>
@@ -43,7 +46,7 @@
  */
 public class NIOSocketHttpDataTransmitter extends NIOHttpDataTransmitter {
 
-    private final Socket socket;
+    private final SocketChannel channel;
     
     protected NIOSocketHttpDataTransmitter(final Socket socket) throws SocketException {
         super();
@@ -53,8 +56,12 @@
         if (socket.getChannel() == null) {
             throw new IllegalArgumentException("Socket does not implement NIO channel");
         }
-        init(socket.getChannel(), socket.getSendBufferSize());
-        this.socket = socket;
+        this.channel = socket.getChannel();
+        initBuffer(socket.getSendBufferSize());
     }
-    
+
+    protected void writeToChannel(final ByteBuffer src) throws IOException {
+        this.channel.write(src);
+    }
+        
 }

Modified: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataReceiverMockup.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataReceiverMockup.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataReceiverMockup.java (original)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataReceiverMockup.java Mon Apr 25 11:40:54 2005
@@ -1,7 +1,9 @@
 package org.apache.http.mockup;
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 
@@ -16,23 +18,25 @@
 
     public static int BUFFER_SIZE = 16;
     
+    private final ReadableByteChannel channel;
+    
     public HttpDataReceiverMockup(final ReadableByteChannel channel, int buffersize) {
         super();
-        init(channel, buffersize);
+        if (channel == null) {
+            throw new IllegalArgumentException("Channel may not be null");
+        }
+        this.channel = channel;
+        initBuffer(buffersize);
     }
 
     public HttpDataReceiverMockup(final byte[] bytes) {
-        super();
-        init(Channels.newChannel(
-                new ByteArrayInputStream(bytes)),
-                BUFFER_SIZE);
+        this(bytes, BUFFER_SIZE);
     }
 
     public HttpDataReceiverMockup(final byte[] bytes, int buffersize) {
         super();
-        init(Channels.newChannel(
-                new ByteArrayInputStream(bytes)),
-                buffersize);
+        this.channel = Channels.newChannel(new ByteArrayInputStream(bytes));
+        initBuffer(buffersize);
     }
 
     public HttpDataReceiverMockup(final String s, final String charset, int buffersize) 
@@ -45,4 +49,16 @@
         this(s.getBytes(charset));
     
     }
+    
+    protected int readFromChannel(final ByteBuffer dst) throws IOException {
+        if (dst == null) {
+            throw new IllegalArgumentException("Byte buffer may not be null");
+        }
+        return this.channel.read(dst);
+    }
+  
+    public boolean isDataAvailable(int timeout) throws IOException {
+        return this.channel.isOpen();
+    }    
+    
 }

Modified: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataTransmitterMockup.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataTransmitterMockup.java?rev=164621&r1=164620&r2=164621&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataTransmitterMockup.java (original)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/mockup/HttpDataTransmitterMockup.java Mon Apr 25 11:40:54 2005
@@ -1,6 +1,8 @@
 package org.apache.http.mockup;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
 
@@ -17,16 +19,27 @@
     
     private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
     
+    private final WritableByteChannel channel;
+    
     public HttpDataTransmitterMockup(final WritableByteChannel channel, int buffersize) {
         super();
-        init(channel, buffersize);
+        if (channel == null) {
+            throw new IllegalArgumentException("Channel may not be null");
+        }
+        this.channel = channel;
+        initBuffer(buffersize);
     }
 
     public HttpDataTransmitterMockup() {
         super();
-        init(Channels.newChannel(this.buffer), BUFFER_SIZE);
+        this.channel = Channels.newChannel(this.buffer);
+        initBuffer(BUFFER_SIZE);
     }
 
+    protected void writeToChannel(final ByteBuffer src) throws IOException {
+        this.channel.write(src);
+    }
+    
     public byte[] getData() {
         return this.buffer.toByteArray();
     }