Java 网络编程之swing图形化QQ聊天室

tech2022-07-14  163

Java写聊天室就要用到网络编程,TCP/UDP都可以,这里用UDP实现。 话不多说,先上图看效果

首先Java通过两个类实现UDP协议顶层的数据报:DatagramPacket对象是数据容器,DatagramSocket是用来发送和接受DatagramPackets的机制。有了这两个类就可以实现UDP通信了,先写一个send发送的方法和receive接收的方法,接受的方法要使用while循环一直监听端口。private String name = "张三";这里是默认的昵称,昵称可以在聊天窗口修改。private int port = 8127;这里是默认端口,可以自定义。Chat()构造方法中写的swing实现的图形化聊天窗口。

使用注意: 1、局域网下两台以上电脑体验效果 ,一台电脑等于在和自己聊天,不能在一台电脑开启两个聊天窗口,端口会冲突。默认局域网ip为:192.168.90.1-254。 2、点击设置昵称默认的昵称就可以更改。 3、退出点击退出按钮退出,不然再次打开会发现聊天框没有信息,因为右上角退出线程没有结束。这时打开任务管理器找到Java™ Platform SE binary进程关闭即可。

聊天业务实现类

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; public class Chat extends JFrame implements ActionListener { private JLabel label1, label2; private JTextField jtextfield1, jTextField2; // 文本框 private JButton button1, button2, button3; // 按钮 private JTextArea textArea; // 文本域 private JPanel southPanel; // 面板 private String name = "张三"; // 默认昵称 private int port = 8127; // 端口号 // 日期格式化 ,后面接收消息方法receive会用到 private static SimpleDateFormat sdf2 = new SimpleDateFormat("a HH:mm:ss"); private SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss"); public Chat() { // 定义窗口宽高常量 final int width = 500; final int height = 600; // 获取屏幕尺寸 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); JFrame myJFrame = new JFrame("聊天室"); // 设置窗口大小 myJFrame.setSize(width, height); // 设置窗口居中显示 myJFrame.setLocation(screenSize.width / 2 - width / 2, screenSize.height / 2 - height / 2); // 网格布局 this.setLayout(new BorderLayout()); label1 = new JLabel("输入昵称", SwingConstants.RIGHT); jtextfield1 = new JTextField(12); JPanel innerPanelCenter = new JPanel(); JPanel innerPanel = new JPanel(); innerPanel.add(label1); innerPanel.add(jtextfield1); innerPanelCenter.add(innerPanel); button1 = new JButton("确定"); innerPanelCenter.add(button1); button1.addActionListener(this); label2 = new JLabel("快开始聊天吧!"); label2.setForeground(Color.red); label2.setBorder(BorderFactory.createTitledBorder("提示")); JPanel northPanel = new JPanel(new BorderLayout()); northPanel.add(innerPanelCenter, BorderLayout.CENTER); northPanel.add(label2, BorderLayout.SOUTH); myJFrame.add(northPanel, BorderLayout.NORTH); textArea = new JTextArea(); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textArea.setFont(new Font("幼圆", Font.PLAIN, 16)); myJFrame.add(new JScrollPane(textArea), BorderLayout.CENTER); southPanel = new JPanel(); southPanel.add(new JLabel()); jTextField2 = new JTextField(30); southPanel.add(jTextField2); button2 = new JButton("发送"); southPanel.add(button2); button3 = new JButton("退出"); southPanel.add(button3); button2.addActionListener(this); button3.addActionListener(this); myJFrame.add(southPanel, BorderLayout.SOUTH); // 设置窗口可见 myJFrame.setVisible(true); } public void actionPerformed(ActionEvent e) { if (e.getSource() == button1) { name = jtextfield1.getText(); // 设置昵称 // jtextfield1.setText(""); } if (e.getSource() == button2) { send(); // 发送 } if (e.getSource() == button3) { System.exit(0); // 退出 } } // 发送消息 public void send() { try { DatagramSocket dSocket = new DatagramSocket(); String string = jTextField2.getText(); jTextField2.setText(""); // 清空输入栏 // 发送编码设为GBK byte[] buf = (name + ":" + string).getBytes("GBK"); for (int i = 1; i < 255; i++) { SocketAddress sAddress = new InetSocketAddress("192.168.90." + i, port); DatagramPacket dPacket = new DatagramPacket(buf, buf.length, sAddress); dSocket.send(dPacket); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 接收消息 public void receive() { try { // 创建一个网络接收对象 DatagramSocket ds = new DatagramSocket(port); while (true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); ds.receive(dp); // 接受数据报包的的方法 ,该方法是一个 阻塞方法 // 将数组转换成字符串并且输出 String str = new String(buf, 0, dp.getLength(), "GBK"); textArea.append(str + " ip:" + dp.getAddress() + " " + (sdf2.format(new Date())) + "\n"); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

聊天室测试类

public class TestChat { public static void main(String[] args) { Chat chat = new Chat(); // 接收消息的方法 chat.receive(); } }
最新回复(0)