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

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

  1. 首先Java通过两个类实现UDP协议顶层的数据报:DatagramPacket对象是数据容器,DatagramSocket是用来发送和接受DatagramPackets的机制。
  2. 有了这两个类就可以实现UDP通信了,先写一个send发送的方法和receive接收的方法,接受的方法要使用while循环一直监听端口。
  3. private String name = "张三";这里是默认的昵称,昵称可以在聊天窗口修改。
  4. private int port = 8127;这里是默认端口,可以自定义。
  5. 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();
	}
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
11-27 10:46
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务