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

由此可见、新建窗口=添加成员

相关推荐
Yan.love30 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶33 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥34 分钟前
java提高正则处理效率
java·开发语言
ROBOT玲玉37 分钟前
Milvus 中,FieldSchema 的 dim 参数和索引参数中的 “nlist“ 的区别
python·机器学习·numpy
智慧老师1 小时前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm1 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
Kai HVZ1 小时前
python爬虫----爬取视频实战
爬虫·python·音视频
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
m0_748244832 小时前
StarRocks 排查单副本表
大数据·数据库·python
V+zmm101342 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm