基本原理
多播可以理解为一个人向多个人(但不是在场的所有人)说话,这样能够提高通话的效率。如果要通知特定的某些人同一件事情,但又不想让其他人知道,使用电话一个一个地通知就非常麻烦,而日常生活的大喇叭进行广播通知,就达不到只通知个别人的目的了。
多播也可以称为组播,采用多播方式,既可以实现一次传送所有目标节点的数据,也可以达到只对特定对象传送数据的目的。IP网络的多播一般通过多播IP地址来实现。多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。
代码:
package MulticastChat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class MulticastChatApplication {
private JFrame sendFrame;
private JFrame receiveFrame;
private JTextArea sendTextArea;
private JTextArea receiveTextArea;
private JTextField messageTextField;
private JButton sendButton;
private MulticastSocket multicastSocket;
private InetAddress group;
private static final String MCAST_ADDR = "233.0.0.1";
private static final int MCAST_PORT = 5150;
public MulticastChatApplication() {
createSendWindow();
createReceiveWindow();
try {
group = InetAddress.getByName(MCAST_ADDR);
multicastSocket = new MulticastSocket(MCAST_PORT);
multicastSocket.joinGroup(group);
receiveMessages();
} catch (IOException e) {
e.printStackTrace();
}
}
private void createSendWindow() {
sendFrame = new JFrame("发送信息窗口");
sendTextArea = new JTextArea(10, 30);
sendTextArea.setEditable(false);
JScrollPane sendScrollPane = new JScrollPane(sendTextArea);
sendFrame.add(sendScrollPane, BorderLayout.CENTER);
messageTextField = new JTextField(20);
sendButton = new JButton("Send");
sendButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String message = messageTextField.getText();
sendMessage(message);
messageTextField.setText("");
}
});
JPanel messagePanel = new JPanel();
messagePanel.add(messageTextField);
messagePanel.add(sendButton);
sendFrame.add(messagePanel, BorderLayout.SOUTH);
sendFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sendFrame.setSize(400, 300);
sendFrame.setVisible(true);
}
private void createReceiveWindow() {
receiveFrame = new JFrame("接收信息窗口");
receiveTextArea = new JTextArea(10, 30);
receiveTextArea.setEditable(false);
JScrollPane receiveScrollPane = new JScrollPane(receiveTextArea);
receiveFrame.add(receiveScrollPane, BorderLayout.CENTER);
receiveFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
receiveFrame.setSize(400, 300);
receiveFrame.setVisible(true);
}
private void receiveMessages() {
Thread receiveThread = new Thread(() -> {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (true) {
try {
multicastSocket.receive(packet);
String receivedMessage = new String(packet.getData(), 0, packet.getLength());
if (receivedMessage.equals("QUIT")) {
break;
}
receiveTextArea.append("RECV: '" + receivedMessage + "' FROM <" + packet.getAddress().getHostAddress() + ">\n");
} catch (IOException e) {
e.printStackTrace();
}
}
multicastSocket.close();
});
receiveThread.start();
}
private void sendMessage(String message) {
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, MCAST_PORT);
try {
multicastSocket.send(packet);
if (message.equals("QUIT")) {
multicastSocket.leaveGroup(group);
multicastSocket.close();
System.exit(0);
} else {
sendTextArea.append("SEND: '" + message + "'\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(MulticastChatApplication::new);
}
}
运行结果: