FULL PRODUCT VERSION :
java version "1.7.0_02"
Java(TM) SE Runtime Environment (build 1.7.0_02-b13)
Java HotSpot(TM) Client VM (build 22.0-b10, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windws 7 (Microsoft Windows [Version 6.1.7601])
A DESCRIPTION OF THE PROBLEM :
I have two proxy server.
One is HTTP proxy listening port 8081.
The other is SOCKS proxy listening port 1081.
ProxySelector returns proxy list for fail-over.
The First proxy is dead, The Seond proxy is alive.
When calling URL.getContent() using HTTP proxy list, fail-over was successful.
When calling socket.connect() using SOCK proxy list, fail-over did not work.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. compile sample code.
2. run the sample
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
* Test for Proxy Alive...
Connecting to /10.13.1.218:8080...
proxy is dead. (java.net.ConnectException: Connection refused: connect)
Connecting to /10.13.1.218:8081...
proxy is alive.
Connecting to /10.13.1.218:1080...
proxy is dead. (java.net.ConnectException: Connection refused: connect)
Connecting to /10.13.1.218:1081...
proxy is alive.
* Test for HTTP Proxy...
http://www.oracle.com/index.html, /10.13.1.218:8080 java.net.ConnectException: Connection refused: connect
Success
* Test for SOCKS Proxy...
socket://www.oracle.com:80, /10.13.1.218:1080 java.net.ConnectException: Connection refused: connect
Success
ACTUAL -
* Test for Proxy Alive...
Connecting to /10.13.1.218:8080...
proxy is dead. (java.net.ConnectException: Connection refused: connect)
Connecting to /10.13.1.218:8081...
proxy is alive.
Connecting to /10.13.1.218:1080...
proxy is dead. (java.net.ConnectException: Connection refused: connect)
Connecting to /10.13.1.218:1081...
proxy is alive.
* Test for HTTP Proxy...
http://www.oracle.com/index.html, /10.13.1.218:8080 java.net.ConnectException: Connection refused: connect
Success
* Test for SOCKS Proxy...
socket://www.oracle.com:80, /10.13.1.218:1080 java.net.ConnectException: Connection refused: connect
socket://www.oracle.com:80, /10.13.1.218:1081 java.net.SocketException: Socket closed
java.net.SocketException: Can't connect to SOCKS proxy:Socket closed
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at dmlim.net.SocksProxyBugTest.testSocks(SocksProxyBugTest.java:118)
at dmlim.net.SocksProxyBugTest.main(SocksProxyBugTest.java:167)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.net.SocketException: Can't connect to SOCKS proxy:Socket closed
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at dmlim.net.SocksProxyBugTest.testSocks(SocksProxyBugTest.java:118)
at dmlim.net.SocksProxyBugTest.main(SocksProxyBugTest.java:167)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package dmlim.net;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
public class SocksProxyBugTest
{
static InetSocketAddress DEAD__HTTP__PROXY_ADDR = new InetSocketAddress("10.13.1.218", 8080);
static InetSocketAddress ALIVE_HTTP__PROXY_ADDR = new InetSocketAddress("10.13.1.218", 8081);
static InetSocketAddress DEAD__SOCKS_PROXY_ADDR = new InetSocketAddress("10.13.1.218", 1080);
static InetSocketAddress ALIVE_SOCKS_PROXY_ADDR = new InetSocketAddress("10.13.1.218", 1081);
static LinkedList<Proxy> HTTP__PROXY_LIST = new LinkedList<Proxy>();
static LinkedList<Proxy> SOCKS_PROXY_LIST = new LinkedList<Proxy>();
static
{
HTTP__PROXY_LIST.add(new Proxy(Proxy.Type.HTTP, DEAD__HTTP__PROXY_ADDR));
HTTP__PROXY_LIST.add(new Proxy(Proxy.Type.HTTP, ALIVE_HTTP__PROXY_ADDR));
SOCKS_PROXY_LIST.add(new Proxy(Proxy.Type.SOCKS, DEAD__SOCKS_PROXY_ADDR));
SOCKS_PROXY_LIST.add(new Proxy(Proxy.Type.SOCKS, ALIVE_SOCKS_PROXY_ADDR));
}
static class MyProxySelector extends ProxySelector
{
@Override
public void connectFailed(URI uri, SocketAddress addr, IOException e)
{
System.err.println(uri + ", " + addr + " " + e);
}
@Override
public List<Proxy> select(URI uri)
{
if ( uri.getScheme().equals("socket") )
return SOCKS_PROXY_LIST;
else
return HTTP__PROXY_LIST;
}
}
public static void testProxyAlive()
{
InetSocketAddress[] addrs = {
DEAD__HTTP__PROXY_ADDR, ALIVE_HTTP__PROXY_ADDR, DEAD__SOCKS_PROXY_ADDR, ALIVE_SOCKS_PROXY_ADDR
};
for ( InetSocketAddress addr : addrs )
{
System.err.println("Connecting to " + addr + "...");
Socket sock = null;
try
{
sock = new Socket(Proxy.NO_PROXY);
sock.connect(addr);
System.err.println("\t proxy is alive.");
}
catch (Exception e)
{
System.err.println("\t proxy is dead. (" + e + ")");
}
finally
{
if ( sock != null ) try { sock.close(); } catch (Exception e) {}
}
}
}
public static void testHttp() throws IOException
{
URL url = new URL("http://www.oracle.com/index.html");
ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream is = null;
try
{
is = (InputStream)url.getContent();
byte[] buf = new byte[1024];
for ( int nRead = 0 ; (nRead = is.read(buf)) != -1 ; )
{
os.write(buf, 0, nRead);
}
}
finally
{
if ( is != null )
is.close();
}
FileOutputStream fos = new FileOutputStream("index.http.html");
fos.write(os.toByteArray());
fos.close();
}
public static void testSocks() throws IOException
{
Socket sock = null;
InputStream is = null;
ByteArrayOutputStream os = new ByteArrayOutputStream();
try
{
sock = new Socket();
sock.connect(new InetSocketAddress("www.oracle.com", 80));
sock.getOutputStream().write("GET /index.html HTTP/1.0\r\nHost: www.oracle.com\r\nUser-Agent: Mozilla/1.0\r\n\r\n".getBytes());
sock.getOutputStream().flush();
is = sock.getInputStream();
byte[] buf = new byte[1024];
for ( int nRead = 0 ; (nRead = is.read(buf)) != -1 ; )
{
os.write(buf, 0, nRead);
}
}
finally
{
if ( is != null )
is.close();
if ( sock != null )
sock.close();
}
FileOutputStream fos = new FileOutputStream("index.socks.html");
fos.write(os.toByteArray());
fos.close();
}
public static void main(String[] args)
{
System.err.println("* Test for Proxy Alive...");
testProxyAlive();
System.err.println();
ProxySelector.setDefault(new MyProxySelector());
try
{
System.err.println("* Test for HTTP Proxy...");
testHttp();
System.err.println("Success");
}
catch (Exception e)
{
e.printStackTrace();
}
System.err.println();
try
{
System.err.println("* Test for SOCKS Proxy...");
testSocks();
System.err.println("Success");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
SUPPORT :
YES