我正在尝试使用java网络中的代理服务器。我已经 阅读了 关于它们的文档,目前正在测试ProxySelector。
我注意到这个ProxySelector在与HttpURLConnection一起使用时和与Socket类一起使用时有两种行为
当与HttpUrlConnection一起使用这个代码时
class CustomSelector extends ProxySelector
@Override
public List<Proxy> select(URI uri)
System.out.println("Selecting");
System.out.println("===============");
return List.of
new Proxy(Proxy.Type.HTTP,new InetSocketAddress("localhost",5000))
,new Proxy(Proxy.Type.HTTP,new InetSocketAddress("localhost",8000))
,Proxy.NO_PROXY
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe)
System.out.println("Failed:"+uri);
System.out.println("Address:"+sa);
System.out.println("Exception:"+sa);
System.out.println("=========================");
public static void main(String[] args)throws Exception
ProxySelector.setDefault(new CustomSelector());
HttpURLConnection con=(HttpURLConnection)new URL("http://192.168.1.2:2000/Test")
.openConnection();
System.out.println(con.getResponseMessage());
con.disconnect();
我得到了预期的输出
Selecting
===============
Failed:http://192.168.1.2:2000/Test
Address:localhost/127.0.0.1:5000
Exception:localhost/127.0.0.1:5000
=========================
Failed:http://192.168.1.2:2000/Test
Address:localhost/127.0.0.1:8000
Exception:localhost/127.0.0.1:8000
=========================
Not-Implemented
这是有道理的,因为端口5000和8000只是假的端口,上面没有运行的服务器,因此在它们上面的连接失败了,最后转到NO_PROXY,它直接连接到我的运行在端口2000上的自定义HttpServer,该端口没有实现所有的功能。
现在我使用同样的程序来处理套接字。我再次验证了我的服务器是在2000端口上运行的。
class CustomSelector extends ProxySelector
@Override
public List<Proxy> select(URI uri)
System.out.println("Selecting");
System.out.println("===============");
return List.of
new Proxy(Proxy.Type.SOCKS,new InetSocketAddress("localhost",5000))
,new Proxy(Proxy.Type.SOCKS,new InetSocketAddress("localhost",8000))
,Proxy.NO_PROXY
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe)
System.out.println("Failed:"+uri);
System.out.println("Address:"+sa);
System.out.println("Exception:"+sa);
System.out.println("=========================");
public static void main(String[] args)throws Exception
ProxySelector.setDefault(new CustomSelector());
try(Socket client=new Socket())
System.out.println("Connecting");
client.connect(new InetSocketAddress(InetAddress.getLocalHost(),2000));
System.out.println("Connected");
我得到这样的输出
Connecting
Selecting
===============
Failed:socket://DESKTOP-1N0I046:2000
Address:localhost/127.0.0.1:5000
Exception:localhost/127.0.0.1:5000
=========================
Failed:socket://DESKTOP-1N0I046:2000
Address:localhost/127.0.0.1:8000
Exception:localhost/127.0.0.1:8000
=========================
Exception in thread "main" java.net.SocketException: Socket closed
at java.base/sun.nio.ch.NioSocketImpl.beginConnect(NioSocketImpl.java:498)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:580)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at java.base/java.net.Socket.connect(Socket.java:583)
at n_networking.proxy.TCPClient.main(TCPClient.java:237)
这不应该发生,因为代理列表中的最后一个选项是NO_PROXY,这意味着没有任何代理的直接连接,这应该是成功的,但似乎ProxySelector从未使用列表中的最后一个选项。
更奇怪的是,如果我把我的ProxyType从SOCKS改为HTTP,如下所示。我知道在这种情况下没有意义,但这只是为了测试目的
@Override
public List<Proxy> select(URI uri)
System.out.println("Selecting");
System.out.println("===============");
return List.of
new Proxy(Proxy.Type.HTTP,new InetSocketAddress("localhost",5000))
,new Proxy(Proxy.Type.HTTP,new InetSocketAddress("localhost",8000))
,Proxy.NO_PROXY
然后一切都会正常。
Connecting
Selecting
===============
Connected
由于某些原因,它跳过了所有的HTTP代理类型,甚至没有测试,然后。
我已经使用Sockets与Proxy.HTTP和它的工作原理是完美的,因为它发出一个CONNECT命令之前发送数据。
这是我的假服务器,我使用这两个测试案例
public static void main(String[] args)throws Exception
try(ServerSocket server=new ServerSocket(2000,0,InetAddress.getLocalHost()))
System.out.println("Main Server Started");
try(Socket socket=server.accept())
System.out.println("Accepted");
socket.getOutputStream().write("HTTP/1.1 501 Not-Implemented\r\n\r\n".getBytes());
socket.getOutputStream().flush();