我正在嘗試在 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();
}
}
}
為什么會有這些差異?我在 Windows 10 中使用 jdk 17.0.2
uj5u.com熱心網友回復:
這似乎是JDK中的一個錯誤:JDK-7141231
盡管java.net.SocksSocketImpl理論上支持代理故障轉移;實際上,這顯然不起作用,因為在第一次失敗的連接嘗試后,套接字被關閉,但是同一個關閉的套接字被用于任何后續連接嘗試,因此失敗并顯示“套接字關閉”(您正在看到)。
將代理型別更改為 HTTP “有效”的原因是因為它執行直接連接,忽略所有其他指定的代理。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/447353.html
