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 byte1024;

// 创建数据包

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

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


版权声明:本文为CSDN博主「Mr.寒风」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/2301_76534800/article/details/134838262

相关推荐
Linux_cy11 小时前
服务器管理工具哪个好用?我用了七八个
运维·服务器·javascript·python·ssh·面板·gmssh
MoRanzhi120311 小时前
第6篇(下)· 使用 PyQt5 实现 2048 高性能计算版:统一运行控制与跨模式安全交接
python·pyqt·进程管理·状态机·软件架构·并发控制·数据一致性
code tsunami11 小时前
【无标题】
开发语言·python
缓慢更新11 小时前
审批的加签与会签:多人意见怎么合
android·java·数据库·低代码·rxjava
CodeGL11 小时前
10、Python基础之进程和线程
开发语言·python
yuniko-n12 小时前
【JUC】volatile 非原子性深入解析
java
TechWayfarer12 小时前
PHP漏洞被利用,怎么揪出攻击IP?
开发语言·python·tcp/ip·网络安全·php
sun_weitao13 小时前
极简版 MCP 工具实现方案
java·linux·服务器
2601_9679801113 小时前
Python列表操作方法详解
python·数据类型·修改·列表操作·功能汇总
金銀銅鐵14 小时前
[Java] 展示增删元素时 LinkedList 的内部变化
java·后端·ai编程