Java利用UDP实现简单群聊
一、创建新项目
 首先新建一个新的项目,并按如下操作

二、实现代码
 界面ChatFrame类
 package 群聊;
 ?
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.net.InetAddress;
 ?
 public abstract class ChatFrame extends JFrame {
 ? ? private JTextArea receiveArea = new JTextArea();//接收文本框,用来显示服务器发送过来的文本
 ? ? private JTextArea sendArea = new JTextArea();//发送文本框,用来显示当前用户要发送的文本
 ?
 ? ? private JButton sendBtn = new JButton("SEND");//发送按键
 ?
 ? ? public ChatFrame() {
 ? ? ? ? this.initFrame();//初始化窗口
 ? ? ? ? this.initComponent();//初始化组件
 ? ? ? ? this.initListener();//初始化监听器
 ? ? ? ? this.receive();//开启监听服务器线程,把接收到的文本显示在receiveArea中
 ? ? }
 ?
 ? ? // 初始化监听器
 ? ? private void initListener() {
 ? ? ? ? // 给发送按键添加监听器,当被点击时调用send()方法
 ? ? ? ? sendBtn.addActionListener(new ActionListener() {
 ? ? ? ? ? ? public void actionPerformed(ActionEvent evt) {
 ? ? ? ? ? ? ? ? send();
 ? ? ? ? ? ? }
 ? ? ? ? });
 ?
 ? ? ? ? // 给发送文本框添加键盘监听器,当按下Ctrl+ENTER时调用send()方法
 ? ? ? ? sendArea.addKeyListener(new KeyAdapter() {
 ? ? ? ? ? ? public void keyPressed(KeyEvent e) {
 ? ? ? ? ? ? ? ? if(e.isControlDown()) {
 ? ? ? ? ? ? ? ? ? ? if(e.getKeyCode() == KeyEvent.VK_ENTER) {
 ? ? ? ? ? ? ? ? ? ? ? ? send();
 ? ? ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? }
 ? ? ? ? });
 ? ? }
 ?
 ? ? // 子类需要重写本方法
 ? ? // 在本方法中使用socket实现消息发送
 ? ? public abstract void sendText(String text);
 ?
 ? ? // 子类需要重写本方法
 ? ? // 在本方法中启动监听服务器线程,调用本类receiveText(String)把接收到的文本显示出来
 ? ? public abstract void receive();
 ?
 ? ? // 本方法用来发送文本
 ? ? public void send() {
 ? ? ? ? // 如果发送文本框中没有文本,弹出警告对话框
 ? ? ? ? if(sendArea.getText().equals("")) {
 ? ? ? ? ? ? javax.swing.JOptionPane.showMessageDialog(this, "空文本不能发送!");
 ? ? ? ? ? ? sendArea.requestFocus();// 把光标归还给发送文本框
 ? ? ? ? ? ? return;
 ? ? ? ? }
 ?
 ? ? ? ? // 调用子类的方法完成文本发送
 ? ? ? ? sendText(sendArea.getText());
 ? ? ? ? // 把发送文本框内容清空
 ? ? ? ? sendArea.setText(null);
 ? ? }
 ?
 ? ? // 本方法完成接收服务器消息的后续工作-在文本框中显示服务器消息,子类的receive()方法在接收服务器消息后可以调用本方法
 ? ? public void receiveText(String text) {
 ? ? ? ? receiveArea.append(text);//把接收到的消息添加到文本框中
 ? ? ? ? // 设置光标位置到最后,如果不设置滚动条不动
 ? ? ? ? receiveArea.setCaretPosition(receiveArea.getText().length());
 ? ? }
 ?
 ? ? // 初始化组件
 ? ? private void initComponent() {
 ? ? ? ? // 使用接收文本框创建滚动窗口(把文本框添加到了滚动窗口中),总是显示纵向滚动条,永不显示横向滚动条
 ? ? ? ? JScrollPane sp1 = new JScrollPane(receiveArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
 ? ? ? ? ? ? ? ? JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 ? ? ? ? // 设置滚动窗口大小、位置、无边框;并把滚动窗口添加到主窗口中
 ? ? ? ? sp1.setSize(606, 350);
 ? ? ? ? sp1.setLocation(14, 20);
 ? ? ? ? sp1.setBorder(null);
 ? ? ? ? this.add(sp1);
 ?
 ? ? ? ? // 设置接收文本框背景色、不可编辑、自动换行
 ? ? ? ? receiveArea.setBackground(new Color(238, 238, 238));
 ? ? ? ? receiveArea.setEditable(false);
 ? ? ? ? receiveArea.setLineWrap(true);
 ?
 ? ? ? ? // 创建发送文本框的滚动窗口,设置自动换行、大小、位置,然后添加到主窗口中
 ? ? ? ? JScrollPane sp2 = new JScrollPane(sendArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
 ? ? ? ? ? ? ? ? JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 ? ? ? ? sendArea.setLineWrap(true);
 ? ? ? ? sp2.setSize(606, 145);
 ? ? ? ? sp2.setLocation(14, 400);
 ? ? ? ? this.add(sp2);
 ?
 ? ? ? ? // 设置发送按键的大小、位置,并添加到主窗口中
 ? ? ? ? sendBtn.setSize(68, 21);
 ? ? ? ? sendBtn.setLocation(553, 560);
 ? ? ? ? this.add(sendBtn);
 ?
 ? ? ? ? // 设置主窗口的标题为当前IP地址
 ? ? ? ? try {
 ? ? ? ? ? ? this.setTitle(InetAddress.getLocalHost().getHostAddress());
 ? ? ? ? } catch (Exception e) {
 ? ? ? ? ? ? throw new RuntimeException(e);
 ? ? ? ? }
 ? ? }
 ?
 ? ? // 初始化主窗口
 ? ? private void initFrame() {
 ? ? ? ? // 设置主窗口的大小、布局管理器为空、背景色、位置、大小不可改变
 ? ? ? ? this.setSize(640, 620);
 ? ? ? ? this.setLayout(null);
 ? ? ? ? this.setBackground(new Color(246, 246, 247));
 ? ? ? ? this.setLocation(350, 50);
 ? ? ? ? this.setResizable(false);
 ?
 ? ? ? ? // 设置主窗口的“X”按钮点击后结束程序
 ? ? ? ? this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 ? ? }
 ?
 ? ? // 显示主窗口方法
 ? ? public void setVisible(boolean b) {
 ? ? ? ? super.setVisible(b);//调用父类的显示方法
 ? ? ? ? sendArea.requestFocus();//让发送文本框得到焦点
 ? ? }
 }
组播聊天SocketChat类
 package 群聊;
 ?
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
 import java.util.Date;
 ?
 /**
 ?* 本类继承了ChatFrame,ChatFrame实现了GUI显示
 ?* 本类负责使用MulticastSocket完成群聊的发送消息与接收消息
 ?*/
 public class SocketChat extends ChatFrame {
 ? ? private MulticastSocket socket;//群组Socket
 ?
 ? ? public SocketChat() throws IOException {
 ? ? ? ? socket = new MulticastSocket(54321);//创建群组Socket,绑定54321端口
 ? ? ? ? //加入虚拟IP:235.235.235.235指定的群组中。虚拟IP范围是:224.0.0.1 和 239.255.255.255
 ? ? ? ? //加入群组后,就可以接收群组的消息,也可以向群组发送消息了
 ? ? ? ? socket.joinGroup(InetAddress.getByName("235.235.235.235"));
 ? ? }
 ?
 ? ? // 发送消息方法
 ? ? public void sendText(String text) {
 ? ? ? ? try {
 ? ? ? ? ? ? // 获取IP地址
 ? ? ? ? ? ? String ip = InetAddress.getLocalHost().getHostAddress();
 ? ? ? ? ? ? // 获取当前时间格式化字符串
 ? ? ? ? ? ? String time = String.format(" <====> %tF %<tT", new Date());
 ? ? ? ? ? ? // 把IP、时间,以及要发送的文本连接在一起
 ? ? ? ? ? ? text = ip + time + "\n" + text + "\n\n";
 ? ? ? ? ? ? // 把文本转换成字节数组
 ? ? ? ? ? ? byte[] buff = text.getBytes();
 ? ? ? ? ? ? // 使用socket向群组发送,socket的send()方法需要两个参数:DatagramPacket、端口号
 ? ? ? ? ? ? // DatagramPacket表示数据包,创建它需要三个参数:数据包的内容、数据包的字节数、要发送的IP地址
 ? ? ? ? ? ? socket.send(new DatagramPacket(buff, buff.length, InetAddress.getByName("235.235.235.235"), 54321));
 ? ? ? ? } catch(Exception e) {
 ? ? ? ? ? ? e.printStackTrace();
 ? ? ? ? }
 ? ? }
 ?
 ? ? // 本方法用来接收群组发送过来的消息
 ? ? public void receive() {
 ? ? ? ? // 创建监听群组消息的线程,并启动它
 ? ? ? ? new Thread() {
 ? ? ? ? ? ? public void run() {
 ? ? ? ? ? ? ? ? // 循环监听
 ? ? ? ? ? ? ? ? while(true) {
 ? ? ? ? ? ? ? ? ? ? try {
 ? ? ? ? ? ? ? ? ? ? ? ? // 创建数据包的字节数组,大小为1KB
 ? ? ? ? ? ? ? ? ? ? ? ? byte[] buff = new byte[1024];
 ? ? ? ? ? ? ? ? ? ? ? ? // 创建数据包
 ? ? ? ? ? ? ? ? ? ? ? ? DatagramPacket dp = new DatagramPacket(buff, buff.length);
 ? ? ? ? ? ? ? ? ? ? ? ? // 接收群组发送过来的消息到数据包中
 ? ? ? ? ? ? ? ? ? ? ? ? // 本方法会阻塞当前线程,直到接收到消息为止
 ? ? ? ? ? ? ? ? ? ? ? ? socket.receive(dp);
 ? ? ? ? ? ? ? ? ? ? ? ? // 把接收到的消息转换成字符串
 ? ? ? ? ? ? ? ? ? ? ? ? String text = new String(dp.getData(), 0, dp.getLength());
 ? ? ? ? ? ? ? ? ? ? ? ? // 调用父类的方法完成显示
 ? ? ? ? ? ? ? ? ? ? ? ? receiveText(text);
 ? ? ? ? ? ? ? ? ? ? } catch(Exception e) {}
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? }
 ? ? ? ? }.start();
 ? ? }
 ?
 ? ? public static void main(String[] args) throws IOException {
 ? ? ? ? SocketChat sc = new SocketChat();
 ? ? ? ? sc.setVisible(true);
 ? ? }
 }
三、运行结果

 运行的第一个窗口成员1
第二个窗口为成员2
第三个窗口为成员3
由此可见、新建窗口=添加成员
 ?
 ?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!