在Java中更换Socket底层的URL连接

3
我有一个使用java.net.URL打开位置以检索一些数据的Java应用程序。现在我需要通过VPN打开连接。它运行的Linux机器现在可以同时打开多个隧道,我需要能够以编程方式告诉应用程序使用哪个隧道。

我相信使用java.net.Socket可以选择虚拟设备来打开连接,但我找不到任何方法来覆盖URL对象以处理所有HTTP流量 - 或在实际打开连接之前替换底层套接字。

那么,如何将我的应用程序连接到特定的网络接口,并保持使用高级对象(如java.net.URL)的优势呢?

现在,我不确定这是否可能,但我想问问聪明的stackoverflow社区...


3
一般来说,应用程序不必采取任何特殊措施来使用VPN连接。但是,操作系统的路由表必须正确设置。那么问题/问题是什么? - Joni
嗨Joni,问题是:我该如何告诉我的应用程序在tun0-00、tun1-00等隧道和默认网络接口之间选择使用哪个隧道?这很重要,因为这些隧道出口位于不同的位置,我需要选择发送流量的位置。 - Alberto Giannetto
你可以在操作系统的路由表中进行配置:“通过这个接口将流量发送到这些IP地址”。你的VPN没有正确设置路由吗?你使用哪个VPN?你使用哪个操作系统? - Joni
问题在于我不想强制我的应用程序仅在访问特定地址(即网关另一端的地址)时使用特定的隧道。实际上,同一时间可能会有多个相同的应用程序实例运行,每个实例可能到达相同的目的地,但使用不同的隧道。我正在CentOS上使用OpenVPN - 不要问为什么... - Alberto Giannetto
为了使其正常工作,您需要为目标使用不同的IP地址范围。如果在同一网络中配置两个网络接口,则操作系统无法保证使用哪一个。因此,您需要在某处添加NAT层,或考虑其他解决方案... - Joni
2个回答

3
我相信您可以注册一个自定义的URLStreamHandlerFactoryjava.net.URL中。每当调用URL上的openConnection()方法时,它将由此注册的自定义工厂处理,从而使您对套接字连接的详细信息具有控制权。
一旦您有了操纵套接字创建的能力,指定使用的网络接口就非常简单了:
NetworkInterface ni = NetworkInterface.getByName("eth0");
Socket socket = new Socket();
socket.bind(ni.getInetAddresses().nextElement());

看起来有一些库提供了设置HTTP连接使用的socketFactory的简单访问方式。例如,可以查看http://faban.org/1.1/docs/api/index.html?com/sun/faban/driver/transport/sunhttp/HttpURLConnection.html


听起来非常有趣。进一步调查发现,可以通过Apache HTTP客户端实现类似的功能,例如在示例中所示。我想可以像您建议的那样创建一个套接字,并使用客户端的连接管理器进行注册。 - Alberto Giannetto
虽然这将套接字的本地地址绑定到特定网络界面的IP上,但操作系统可以使用同一网络中的任何其他接口来发送流量。 - Joni

0
您可以实现自定义的SocketImplFactory,然后使用Socket.setSocketImplFactory将其设为默认值。但是我不确定如何在客户端选择网络接口,这应该是路由器的功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接