0

我试图了解多播是如何工作的,因此我正在尝试一下。

情况

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

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

预期行为

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

观察到的行为/问题

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

结果是这样的(可以看到只有MulticastEchoClient2进程接收到服务器的响应):

组播回声服务器 组播EchoClient1 组播EchoClient2

代码

服务器代码

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);
    }
}
4

1 回答 1

2

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

于 2014-06-09T01:32:22.177 回答