Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-UDP多播仅在本地主机上工作_Java_Networking_Udp_Multicast - Fatal编程技术网

Java-UDP多播仅在本地主机上工作

Java-UDP多播仅在本地主机上工作,java,networking,udp,multicast,Java,Networking,Udp,Multicast,我最近在我的多人游戏中实现了多播,以定位在玩家网络上运行的游戏。我创建了两个类,Heart和Listener。我遇到的问题是,如果我在另一台计算机上运行某个部件,则侦听器只能通过localhost听到心跳声 心脏: package net.jibini.networking.udp; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; impor

我最近在我的多人游戏中实现了多播,以定位在玩家网络上运行的游戏。我创建了两个类,
Heart
Listener
。我遇到的问题是,如果我在另一台计算机上运行某个部件,则侦听器只能通过
localhost
听到心跳声

心脏:

package net.jibini.networking.udp;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import net.jibini.networking.packets.Packet;

public class Heart implements Runnable 
{
    private String groupName = "229.5.38.17";
    private int port = 4567;
    MulticastSocket multicastSocket;
    DatagramPacket datagramPacket;
    public boolean beating = true;
    public Packet toSend;

    public Heart(int connectionListenerPort, Packet toSend) 
    {
        try 
        {
            this.toSend = toSend;
            multicastSocket = new MulticastSocket();
            multicastSocket.setReuseAddress(true);
            InetAddress group = InetAddress.getByName(groupName);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(toSend);
            objectOutputStream.flush();
            objectOutputStream.close();
            byte[] buf = byteArrayOutputStream.toByteArray();
            datagramPacket = new DatagramPacket(buf, buf.length, group, port);
            new Thread(this).start();
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }

    @Override
    public void run() 
    {
        while (beating) 
        {
            beat();
            try 
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }

    private void beat() {
        try 
        {
            multicastSocket.send(datagramPacket);
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }
}
听众:

package net.jibini.networking.udp;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import net.jibini.networking.packets.Packet;

public class Listener implements Runnable 
{
    private boolean run = true;
    private String groupName = "229.5.38.17";
    MulticastSocket multicastSocket;
    public OnFound onFound;

    public Listener(OnFound onFound) 
    {
        try 
        {
            multicastSocket = new MulticastSocket(4567);
            multicastSocket.setReuseAddress(true);
            multicastSocket.joinGroup(InetAddress.getByName(groupName));
            this.onFound = onFound;
            new Thread(this).start();
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }

    @Override
    public void run() 
    {
        while (run) 
        {
            DatagramPacket datagramPacket = new DatagramPacket(new byte[1500], 1500);
            try 
            {
                multicastSocket.receive(datagramPacket);
                Packet beat = getBeat(datagramPacket);
                if (beat != null) 
                {
                    onFound.onFound(datagramPacket.getAddress(), beat);
                }
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }

    public void stop() 
    {
        run = false;
    }

    /*private boolean isLocalhost(String hostAddress) 
    {
        boolean isLocalhost = false;
        Enumeration<NetworkInterface> networkInterfaces;
        try 
        {
            networkInterfaces = NetworkInterface.getNetworkInterfaces();
            if (networkInterfaces != null) 
            {
                OUTER:
                while (networkInterfaces.hasMoreElements()) 
                {
                    NetworkInterface networkInterface = networkInterfaces.nextElement();
                    Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                    if (inetAddresses != null) 
                    {
                        while (inetAddresses.hasMoreElements()) 
                        {
                            InetAddress inetAddress = inetAddresses.nextElement();
                            if (hostAddress.equals(inetAddress.getHostAddress())) 
                            {
                                isLocalhost = true;
                                break OUTER;
                            }
                        }
                    }
                }
            }
        } 
        catch (SocketException e) 
        {
            e.printStackTrace();
        }
        return isLocalhost;
    }*/

    private Packet getBeat(DatagramPacket datagramPacket) 
    {
        Packet beat = null;
        byte[] data = datagramPacket.getData();
        if (data != null) 
        {
            try 
            {
                ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data));
                beat = (Packet) objectInputStream.readObject();
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            } 
            catch (ClassNotFoundException e) 
            {
                e.printStackTrace();
            }
        }
        return beat;
    }

    public static class OnFound 
    {
        public void onFound(InetAddress inet, Packet beat) {}
    }
}
package net.jibini.networking.udp;
导入java.io.ByteArrayInputStream;
导入java.io.IOException;
导入java.io.ObjectInputStream;
导入java.net.DatagramPacket;
导入java.net.InetAddress;
导入java.net.MulticastSocket;
导入java.net.NetworkInterface;
导入java.net.SocketException;
导入java.util.Enumeration;
导入net.jibini.networking.packets.Packet;
公共类侦听器实现可运行
{
私有布尔运行=true;
私有字符串groupName=“229.5.38.17”;
多播套接字多播套接字;
已发现的公共OnFound;
公共侦听器(OnFound-OnFound)
{
尝试
{
multicastSocket=新的multicastSocket(4567);
multicastSocket.setReuseAddress(真);
multicastSocket.joinGroup(InetAddress.getByName(groupName));
this.onFound=onFound;
新线程(this.start();
} 
捕获(IOE异常)
{
e、 printStackTrace();
}
}
@凌驾
公开募捐
{
while(运行)
{
DatagramPacket DatagramPacket=新的DatagramPacket(新字节[1500],1500);
尝试
{
多播套接字接收(datagramPacket);
数据包节拍=getBeat(数据包节拍);
如果(节拍!=null)
{
onFound.onFound(datagramPacket.getAddress(),beat);
}
} 
捕获(IOE异常)
{
e、 printStackTrace();
}
}
}
公共停车场()
{
运行=错误;
}
/*专用布尔值isLocalhost(字符串主机地址)
{
布尔值isLocalhost=false;
枚举网络接口;
尝试
{
networkInterfaces=NetworkInterface.getNetworkInterfaces();
if(网络接口!=null)
{
外部:
while(networkInterfaces.hasMoreElements())
{
NetworkInterface NetworkInterface=networkInterfaces.nextElement();
枚举inetAddresses=networkInterface.getInetAddresses();
if(inetAddresses!=null)
{
while(inetAddresses.hasMoreElements())
{
InetAddress InetAddress=inetAddresses.nextElement();
if(hostAddress.equals(inetAddress.getHostAddress()))
{
isLocalhost=true;
打破外部;
}
}
}
}
}
} 
捕获(SocketException e)
{
e、 printStackTrace();
}
返回isLocalhost;
}*/
专用数据包getBeat(数据包数据包)
{
包拍=空;
byte[]data=datagramPacket.getData();
如果(数据!=null)
{
尝试
{
ObjectInputStream ObjectInputStream=新的ObjectInputStream(新的ByteArrayInputStream(数据));
beat=(数据包)objectInputStream.readObject();
} 
捕获(IOE异常)
{
e、 printStackTrace();
} 
catch(classnotfounde异常)
{
e、 printStackTrace();
}
}
回击;
}
找到公共静态类
{
找到公共void onFound(InetAddress inet,数据包节拍){}
}
}
我怎样才能让听者听到另一台电脑的节拍呢

编辑: 查找本地IPv4地址

public static InetAddress localAddress()
{
    String ip;
    try {
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface iface = interfaces.nextElement();
            if (iface.isLoopback() || !iface.isUp())
                continue;

            Enumeration<InetAddress> addresses = iface.getInetAddresses();
            while(addresses.hasMoreElements()) {
                InetAddress addr = addresses.nextElement();
                ip = addr.getHostAddress();
                if (ip.startsWith("10.") || ip.startsWith("172.31.") || ip.startsWith("192.168"))
                    return addr;
            }
        }
    } catch (SocketException e) {
        throw new RuntimeException(e);
    }
    return null;
}
publicstaticinetaddress localAddress()
{
字符串ip;
试一试{
枚举接口=NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements()){
NetworkInterface iface=interfaces.nextElement();
if(iface.isLoopback()| |!iface.isUp())
继续;
枚举地址=iface.getInetAddresses();
while(addresses.hasMoreElements()){
InetAddress addr=地址.nextElement();
ip=addr.getHostAddress();
如果(ip.起始带(“10”)| | ip.起始带(“172.31”)| | ip.起始带(“192.168”))
返回地址;
}
}
}捕获(SocketException e){
抛出新的运行时异常(e);
}
返回null;
}

您需要确保您的侦听器已在正确的接口上加入多播组,并且您的发送者正在正确的接口上发送

在这两种情况下,您都可以通过
setInterface
setNetworkInterface
方法执行此操作

假设发送方的IP地址为192.168.1.1和192.168.2.1,接收方的IP地址为192.168.1.2和192.168.2.2。如果您希望您的发件人从192.168.1.1发送,请拨打:

multicastSocket.setInterface(InetAddress.getByName("192.168.1.1"));
然后,您的接收器需要在192.168.1.2上接收:

multicastSocket.setInterface(InetAddress.getByName("192.168.1.2"));
multicastSocket.joinGroup(InetAddress.getByName(groupName));
如果您希望您的接收器通过多个接口接收,请多次调用
joinGroup
,首先调用
setInterface

multicastSocket.setInterface(InetAddress.getByName("192.168.1.2"));
multicastSocket.joinGroup(InetAddress.getByName(groupName));
multicastSocket.setInterface(InetAddress.getByName("192.168.2.2"));
multicastSocket.joinGroup(InetAddress.getByName(groupName));
编辑:

如果您不知道本地IP地址,可以使用
InetAddress.getLocalHost()
获取与计算机主机名关联的IP。如果系统上有多个IP,可以调用
NetworkInterface.getNetworkInterfaces()
for (NetworkInterface intf: NetworkInterface.getNetworkInterfaces()) {
    for (InetAddress addr: intf.getInetAddresses()) {
        System.out.println("interface " + intf + ": address " + addr);
    }
}
    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface iface = interfaces.nextElement();
        if (iface.isLoopback() || !iface.isUp())
            continue;

        Enumeration<InetAddress> addresses = iface.getInetAddresses();
        while(addresses.hasMoreElements()) {
            InetAddress addr = addresses.nextElement();
            multicastSocket.setInterface(addr);
            multicastSocket.send(datagramPacket);
        }
    }
    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface iface = interfaces.nextElement();
        if (iface.isLoopback() || !iface.isUp())
            continue;

        Enumeration<InetAddress> addresses = iface.getInetAddresses();
        while(addresses.hasMoreElements()) {
            InetAddress addr = addresses.nextElement();
            multicastSocket.setInterface(addr);
            multicastSocket.joinGroup(InetAddress.getByName(groupName));
        }
    }