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

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

相关推荐
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
阿斯卡码1 小时前
jupyter添加、删除、查看内核
ide·python·jupyter
霖雨2 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404192 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
P.H. Infinity3 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
爱吃土豆的程序员3 小时前
java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
xml·java·cdata