Я пытаюсь понять, как работает многоадресная рассылка, поэтому немного экспериментирую с ней.
Ситуация
Я построил простой сервер с MulticastSocket
, прослушивающим порт 1250. Он просто повторяет полученное сообщение.
Затем я создал простой клиент, также с MulticastSocket
, прослушивающий порт 4711. Он отправляет String-Message на сервер и ждет любого сообщения, которое вернется.
Ожидаемое поведение
Я хочу, чтобы два или более клиентов отправляли свое собственное уникальное сообщение на сервер и получали все ответы, которые сервер отправляет обратно группе многоадресной рассылки, прослушивающей порт 4711.
Наблюдаемое поведение / проблема
Как только я запускаю более одного экземпляра клиента, все ответы от сервера получает только первый клиент, который присоединился к группе. Все остальные клиенты, которые присоединились к группе многоадресной рассылки на порту 4711, ничего не получают. Почему это и как решить проблему?
Результат выглядит следующим образом (вы можете видеть, что только процесс 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);
}
}