我正在尝试在JAVA中发送带有数据报的UDP,而我的机器有几个不同IP的网卡。
如何设置我希望从哪个网卡发送数据包? (假设机器上有多个?)
编辑我
我没有使用Socket,我正在使用DatagramSocket并试图像这样进行绑定:
/*binding */
DatagramSocket ds = new DatagramSocket(1111);
NetworkInterface nif = NetworkInterface.getByIndex(nicIndex);
Enumeration<InetAddress> nifAddresses = nif.getInetAddresses();
ds.bind(new InetSocketAddress(nifAddresses.nextElement(), 0));
但是当我这样做时,我再也无法连接(或者无法获取数据包......)。 问题是我有2个NIC,但一个用于INTERNAL网络,另一个用于Internet。 我需要我所有的服务器数据只能在INTERNAL上...
编辑II
澄清。 这个应用程序是一个服务器 - SERVER有2个NICS。一个LAN,一个用于WAN。
另一种方法是以某种方式指定ROUTING - 意味着告诉每个数据包确切地使用哪个NIC ..
如何在JAVA中进行这样的路由?
答案 0 :(得分:4)
我遇到了同样的问题。解决问题并不是立竿见影的,但最后我写了一些对你有用的代码:
//set Network Interface
NetworkInterface nif = NetworkInterface.getByName("tun0");
if(nif==null){
System.err.println("Error getting the Network Interface");
return;
}
System.out.println("Preparing to using the interface: "+nif.getName());
Enumeration<InetAddress> nifAddresses = nif.getInetAddresses();
InetSocketAddress inetAddr= new InetSocketAddress(nifAddresses.nextElement(),0);
//socket.bind(new InetSocketAddress(nifAddresses.nextElement(), 0));
DatagramSocket socket = new DatagramSocket(inetAddr);
System.out.println("Interface setted");
我使用了大量的输出来确保代码工作正常并且它看起来像是这样做的,我仍然在努力但我想这对你的问题来说已经足够了
答案 1 :(得分:2)
Socket
类的constructor 带有localAddr
个参数。那可能适用于你?
修改强> 1)不要用Java进行路由,将其留给操作系统。
2)我相信你已经访问了All About Datagrams?
3)服务器可以绑定到0.0.0.0
(即机器上的任何IP),如果您只在DatagramSocket
构造函数中指定端口,或者如果它可以绑定到特定接口,则会发生这种情况你选择了DatagramSocket(int port, InetAddress laddr)
构造函数 - 这就是你应该做的!
4)然后客户端发送它需要发送的任何内容,服务器可以使用3)中创建的套接字和packet.getAddress()/ packet.getPort()目的地进行响应。
干杯,
答案 2 :(得分:1)
来自教程文档Here, “要发送数据,系统会确定使用哪个接口。但是,如果您有首选项或需要指定要使用的NIC,则可以在系统中查询相应的接口并在所需的接口上查找地址。用“。
可以通过编程方式访问NetworkInterFaces,
Enumeration en = NetworkInterface.getNetworkInterfaces();
迭代每个可以获得与之关联的InetAddress并使用InetAddress构建数据报套接字。
这个问题有很好的信息 - How to enumerate IP addresses of all enabled NIC cards from Java?
希望有所帮助,
答案 3 :(得分:1)
这是我使用的大部分完整代码。就我而言,我知道我的连接使用的IP地址前缀。您可能需要查找接口的名称,并将其与存储在配置文件中的值进行比较。
请注意使用MulticastSocket而不是DatagramSocket,因此setNetworkInterface方法可用于绑定所需的接口。由于MulticastSocket是DatagramSocket的子类,因此交换机通常不会产生任何问题。
@Override
public void connect() throws InterruptedException
{
NetworkInterface iFace;
iFace = findNetworkInterface();
connectControlBoard(iFace);
connectUTBoards(iFace);
}//end of Capulin1::connect
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Capulin1:findNetworkInterface
//
// Finds the network interface for communication with the remotes. Returns
// null if no suitable interface found.
//
// The first interface which is connected and has an IP address beginning with
// 169.254.*.* is returned.
//
// NOTE: If more than one interface is connected and has a 169.254.*.*
// IP address, the first one in the list will be returned. Will need to add
// code to further differentiate the interfaces if such a set up is to be
// used. Internet connections will typically not have such an IP address, so
// a second interface connected to the Internet will not cause a problem with
// the existing code.
//
// If a network interface is not specified for the connection, Java will
// choose the first one it finds. The TCP/IP protocol seems to work even if
// the wrong interface is chosen. However, the UDP broadcasts for wake up calls
// will not work unless the socket is bound to the appropriate interface.
//
// If multiple interface adapters are present, enabled, and running (such as
// an Internet connection), it can cause the UDP broadcasts to fail.
//
public NetworkInterface findNetworkInterface()
{
logger.logMessage("");
NetworkInterface iFace = null;
try{
logger.logMessage("Full list of Network Interfaces:" + "\n");
for (Enumeration<NetworkInterface> en =
NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
logger.logMessage(" " + intf.getName() + " " +
intf.getDisplayName() + "\n");
for (Enumeration<InetAddress> enumIpAddr =
intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
String ipAddr = enumIpAddr.nextElement().toString();
logger.logMessage(" " + ipAddr + "\n");
if(ipAddr.startsWith("/169.254")){
iFace = intf;
logger.logMessage("==>> Binding to this adapter...\n");
}
}
}
}
catch (SocketException e) {
logger.logMessage(" (error retrieving network interface list)" + "\n");
}
return(iFace);
}//end of Capulin1::findNetworkInterface
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Capulin1::connectControlBoards
//
public void connectControlBoard(NetworkInterface pNetworkInterface)
throws InterruptedException
{
logger.logMessage("Broadcasting greeting to all Control boards...\n");
MulticastSocket socket;
try{
socket = new MulticastSocket(4445);
if (pNetworkInterface != null) {
try{
socket.setNetworkInterface(pNetworkInterface);
}catch (IOException e) {}//let system bind to default interface
}
}
catch (IOException e) {
logSevere(e.getMessage() + " - Error: 204");
logger.logMessage("Couldn't create Control broadcast socket.\n");
return;
}
...use the socket here...