UDP多播与Java:整个多播组无法接收消息

时间:2014-06-05 09:05:44

标签: java sockets udp multicast multicastsocket

我试图理解多播是如何工作的,因此我正在试验它。

场合

我构建了一个简单的服务器,其中有MulticastSocket,侦听端口1250.它只是回显它收到的消息。

接下来我构建了一个简单的客户端,同时使用MulticastSocket,侦听端口4711.它向服务器发送一个String-Message并等待返回的任何消息。

预期行为

我希望两个或更多客户端向服务器发送自己唯一的消息,并接收服务器发送回端口4711上侦听的多播组的所有响应。

观察到的行为/问题

只要我启动客户端的多个实例,服务器的所有响应都只能由加入该组的第一个客户端接收。在端口4711上加入多播组的所有其他客户端都不会收到任何内容。为什么这样,我该如何解决这个问题?

结果如下(您可以看到只有进程 MulticastEchoClient2 收到服务器的响应):

MulticastEchoServer MulticastEchoClient1 MulticastEchoClient2

代码

服务器的代码

public class MulticastEchoServer
{
    public static void main(String[] args)
    {
        if (args.length != 2)
        {
            System.out.println("Wrong usage of parameters! <MulticastAddress><id>");
            return;
        }

        UDPMulticastSocket socket = null;
        String id = args[1];

        try
        {
            socket = new UDPMulticastSocket(1250);
            System.out.println("Socket created...");

            socket.join(args[0]);

            while(true)
            {
                String msg = socket.receive(1024);
                System.out.println("Message received: " + msg + " from " + socket.getSenderAddress() + ":" + socket.getSenderPort());

                if (msg.toLowerCase().equals("quit"))
                {
                    System.out.println("Shutting down...");
                    break;
                }

                socket.reply("Reply from " + id + " -> " + msg);
            }

            socket.leave(args[0]);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        if (socket != null)
        {
            socket.close();
            System.out.println("Shutting down...");
        }
    }
}

客户代码

public class MulticastEchoClient
{
    public final static int MESSAGES = 10000;

    public static void main(String[] args)
    {
        if (args.length != 3)
        {
            System.out.println("Wrong usage of parameters: <Multicast-Address><Address of Server><id>");
            return;
        }

        UDPMulticastSocket socket = null;
        String id = args[2];

        try
        {
            socket = new UDPMulticastSocket(4711);
            socket.setTimeout(1000);
            System.out.println("Socket created...");

            socket.join(args[0]);
            InetAddress srvrAddress = InetAddress.getByName(args[1]);

            for (int i = 0; i < MESSAGES; i++)
            {
                socket.send(id + " sending: " + i, srvrAddress, 1250);

                try
                {
                    while(true)
                    {
                        String msg = socket.receive(1024);
                        System.out.println("Message received: " + msg + " from " + socket.getSenderAddress() + ":" + socket.getSenderPort());
                    }
                }
                catch (IOException e)
                {
                    System.out.println("All messages received...");
                }
            }

            socket.leave(args[0]);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        if (socket != null)
        {
            socket.close();
            System.out.println("Shutting down...");
        }
    }
}

实用程序类

public class UDPSocket
{
    protected DatagramSocket socket;
    private InetAddress senderAddress;
    private int senderPort;

    //constructors
    protected UDPSocket(DatagramSocket socket)
    {
        this.socket = socket;
    }

    public UDPSocket() throws SocketException
    {
        this(new DatagramSocket());
    }

    public UDPSocket(int port) throws SocketException
    {
        this(new DatagramSocket(port));
    }

    //getters
    public InetAddress getSenderAddress()
    {
        return senderAddress;
    }

    public int getSenderPort()
    {
        return senderPort;
    }

    //setters
    public void setTimeout(int timeout) throws SocketException
    {
        socket.setSoTimeout(timeout);
    }

    //methods
    public void send(String s, InetAddress rcvrAddress, int rcvrPort) throws IOException
    {
        byte[] data = s.getBytes();
        DatagramPacket outPacket = new DatagramPacket(data, 0, data.length, rcvrAddress, rcvrPort);

        socket.send(outPacket);
    }

    public String receive(int maxBytes) throws IOException
    {
        byte[] data = new byte[maxBytes];
        DatagramPacket inPacket = new DatagramPacket(data, 0, data.length);
        socket.receive(inPacket);

        senderAddress = inPacket.getAddress();
        senderPort = inPacket.getPort();

        //return new String(data, 0, data.length);
        return new String(data, 0, inPacket.getLength());
    }

    public void reply(String s) throws IOException
    {
        if (senderAddress != null)
        {
            send(s, senderAddress, senderPort);
        }
        else
        {
            throw new IOException("ERROR: No one to reply to!");
        }
    }

    public void close()
    {
        socket.close();
    }
}

public class UDPMulticastSocket extends UDPSocket
{
    public UDPMulticastSocket(int port) throws IOException
    {
        super(new MulticastSocket(port));
    }

    public UDPMulticastSocket() throws IOException
    {
        super(new MulticastSocket());
    }

    public void join(String mcAddress) throws IOException
    {
        InetAddress ia = InetAddress.getByName(mcAddress);
        ((MulticastSocket) socket).joinGroup(ia);
    }

    public void leave(String mcAddress) throws IOException
    {
        InetAddress ia = InetAddress.getByName(mcAddress);
        ((MulticastSocket) socket).leaveGroup(ia);
    }
}

1 个答案:

答案 0 :(得分:2)

您正在回复发送地址,因此只有发送地址才会收到回复。如果要回复组播组,请回复组播组,而不是发送地址。