我在同一主机上同时运行服务器和客户端的Messenger程序(Mac Pro PC)。服务器和客户端之间的单播连接在同一主机上按预期工作。客户端通过单播连接向服务器发送消息。服务器将消息发送到多播地址。客户端侦听多播地址,并假设从服务器接收消息。
多播连接无法正常工作。服务器无例外地发送消息,但客户端没有通过多播接收消息。这是发送方和接收方的代码段。
public interface SocketMessengerConstants
{
// address for multicast datagrams
public static final String MULTICAST_ADDRESS = "239.0.0.1";
// port for listening for multicast datagrams
public static final int MULTICAST_LISTENING_PORT = 5555;
// port for sending multicast datagrams
public static final int MULTICAST_SENDING_PORT = 5554;
......
public class MulticastSender implements Runnable
{
private byte[] messageBytes; // message data
public MulticastSender( byte[] bytes )
{
messageBytes = bytes; // create the message
} // end MulticastSender constructor
// deliver message to MULTICAST_ADDRESS over DatagramSocket
public void run()
{
try // deliver message
{
// create DatagramSocket for sending message
DatagramSocket socket =
new DatagramSocket( MULTICAST_SENDING_PORT );
// use InetAddress reserved for multicast group
InetAddress group = InetAddress.getByName( MULTICAST_ADDRESS );
// create DatagramPacket containing message
System.out.println(messageBytes.length);
DatagramPacket packet = new DatagramPacket( messageBytes,
messageBytes.length, group, MULTICAST_LISTENING_PORT );
socket.send( packet ); // send packet to multicast group
socket.close(); // close socket
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
} // end catch
} // end method run
} // end class MulticastSender
public class PacketReceiver implements Runnable
{
private MessageListener messageListener; // receives messages
private MulticastSocket multicastSocket; // receive broadcast messages
private InetAddress multicastGroup; // InetAddress of multicast group
private boolean keepListening = true; // terminates PacketReceiver
public PacketReceiver( MessageListener listener )
{
messageListener = listener; // set MessageListener
try // connect MulticastSocket to multicast address and port
{
// create new MulticastSocket
multicastSocket = new MulticastSocket(
MULTICAST_LISTENING_PORT );
// use InetAddress to get multicast group
multicastGroup = InetAddress.getByName( MULTICAST_ADDRESS );
// join multicast group to receive messages
multicastSocket.joinGroup( multicastGroup );
// set 5 second timeout when waiting for new packets
multicastSocket.setSoTimeout( 5000 );
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
} // end catch
} // end PacketReceiver constructor
// listen for messages from multicast group
public void run()
{
// listen for messages until stopped
while ( keepListening )
{
// create buffer for incoming message
byte[] buffer = new byte[ MESSAGE_SIZE ];
// create DatagramPacket for incoming message
DatagramPacket packet = new DatagramPacket( buffer,
MESSAGE_SIZE );
try // receive new DatagramPacket (blocking call)
{
multicastSocket.receive( packet );
} // end try
catch ( SocketTimeoutException socketTimeoutException )
{
continue; // continue to next iteration to keep listening
} // end catch
catch ( IOException ioException )
{
ioException.printStackTrace();
break;
} // end catch
// put message data in a String
String message = new String( packet.getData() );
message = message.trim(); // trim whitespace from message
System.out.println(message);
// tokenize message to retrieve user name and message body
StringTokenizer tokenizer = new StringTokenizer(
message, MESSAGE_SEPARATOR );
// ignore messages that do not contain a user
// name and message body
if ( tokenizer.countTokens() == 2 )
{
// send message to MessageListener
messageListener.messageReceived(
tokenizer.nextToken(), // user name
tokenizer.nextToken() ); // message body
} // end if
} // end while
try
{
multicastSocket.leaveGroup( multicastGroup ); // leave group
multicastSocket.close(); // close MulticastSocket
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
} // end catch
} // end method run
......
} // end class PacketReceiver
路由器上的多播功能已禁用。我从路由器的网关中取消选中“禁用IGMP代理”。但是仍然没有收到多播数据报包。
更新:程序位于防火墙后面。防火墙允许传入连接后,一切都会按预期进行。