[java]聊天室设计与实现

本聊天系统包括三个部分,客户端、服务器以及数据库的连接,客户端包含了5个java文件,分别为主类client.java、登录窗口类login.java、上线提醒类onlinewindow.java、消息提示音类playWAV.java、注册类Register.java.数据库包含一个数据库连接文件DB.java,服务端包括4个java文件,分别是客户端服务线程类ClientThread.java,服务端线程类文件ServerThread.java,服务端界面设计类ServerUI.java,用户信息类User.java.

 数据库使用了一个hellouser表用来记录用户注册和登录的账号密码。

项目网盘链接:链接:https://pan.baidu.com/s/1LkfLI7TWcZz4TiFENEx80w
提取码:bgmz

 

 

功能模块设计

①登录功能

需要提供支持用户登陆以及身份验证的WEB界面和实现后台对应功能的模块

②注册功能

需要提供支持用户注册用户名和密码且密码要输入两次相同的模块

③私聊

用户选择在线的某一个用户进行聊天,且不能和自己聊天或空发消息模块

④群聊

用户选择“全部”输入想要发送的消息,点击发送模块

⑤上线提醒

当某个用户上显示有小窗口提醒某个用户上线模块

⑥消息接收提示音

当有用户发送消息给另一个用户时,另一个用户会听到提示音消息,提醒有消息收到模块

代码(部分)

Client.java

// 连接服务器

private void ConnectServer() {

try {

socket = new Socket(ip, port);// 根据端口号和服务器IP建立连接

writer = new PrintWriter(socket.getOutputStream());

reader = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

// 发送客户端基本信息(用户名和IP地址)

sendMessage(name + "@" + socket.getLocalAddress().toString());

// 开启不断接收消息的线程

messageThread = new MessageThread(reader);

messageThread.start();

isConnected = true;// 已经连接上了

JOptionPane.showMessageDialog(frame, name + " 连接服务器成功!");

frame.setVisible(true);


} catch (Exception e) {

isConnected = false;// 未连接上

JOptionPane.showMessageDialog(frame, "连接服务器异常:" + e.getMessage(),

"错误", JOptionPane.ERROR_MESSAGE);

}

}

// 断开连接

public synchronized boolean ConnectClose() {

try {

sendMessage("CLOSE");// 发送断开连接命令给服务器

messageThread.stop();// 停止接受消息线程

// 释放资源

if (reader != null) {

reader.close();

}

if (writer != null) {

writer.close();

}

if (socket != null) {

socket.close();

}

isConnected = false;

return true;

} catch (IOException e) {

JOptionPane.showMessageDialog(frame, name + " 断开连接服务器成功!");

isConnected = true;

return false;

}

}
Login.java

frame = new JFrame("欢迎来到聊天室!");

// 设置窗体的标题图标

Image touxiang = new ImageIcon("image/icon.png").getImage();

frame.setIconImage(touxiang);

// 背景图片

background = new ImageIcon("image/bg.jpg");

JLabel label = new JLabel(background);// 把背景图片显示在标签里

label.setBounds(0, 0, background.getIconWidth(),

background.getIconHeight());// 把标签的大小位置设置为图片刚好填充整个面板

// 把内容窗格转化为JPanel,才能用方法setOpaque()来使内容窗格透明

imagePanel = (JPanel) frame.getContentPane();

imagePanel.setOpaque(false);

imagePanel.setLayout(null);// 设置布局方式为绝对定位

onlinewindow.java

public void run() {

frame = new JFrame("上线提醒");

frame.setIconImage(new ImageIcon("image/icon.png").getImage());// 更改JFrame的图标

showMsg = new JTextArea();

showMsg.setText(" "+name+" 上线啦!");

showMsg.setFont(new Font("宋体", Font.BOLD, 25));

showMsg.setEditable(false);// 显示消息框不可编辑

showMsg.setForeground(Color.WHITE);

playWAV.java

public void Play(String s) {

this.str = s;

try {

AudioInputStream ais = AudioSystem

.getAudioInputStream(new File(str));// 获得音频输入流

AudioFormat baseFormat = ais.getFormat();// 指定声音流中特定数据安排

// System.out.println("baseFormat=" + baseFormat);

DataLine.Info info = new DataLine.Info(SourceDataLine.class,

baseFormat);

// System.out.println("info=" + info);

SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);

// 从混频器获得源数据行

// System.out.println("line=" + line);

line.open(baseFormat);// 打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可操作。

line.start();// 允许数据行执行数据 I/O

int BUFFER_SIZE = 4000 * 4;

int intBytes = 0;

byte[] audioData = new byte[BUFFER_SIZE];

while (intBytes != -1) {

intBytes = ais.read(audioData, 0, BUFFER_SIZE);// 从音频流读取指定的最大数量的数据字节,并将其放入给定的字节数组中。

if (intBytes >= 0) {

int outBytes = line.write(audioData, 0, intBytes);// 通过此源数据行将音频数据写入混频器。

}

}

Register.java

private void registerUser(String name, String pwd1, String pwd2) {

if (pwd1.equals(pwd2)) {

UserDB c = new UserDB(name, pwd2);

if (c.addsql() == true) {

JOptionPane.showMessageDialog(new JFrame(),

"注册成功!\n请记住您的账号和密码", "恭喜", JOptionPane.CLOSED_OPTION);

} else {

JOptionPane.showMessageDialog(new JFrame(), "注册失败,换个用户名试试吧!", "错误",

JOptionPane.ERROR_MESSAGE);

}

} else {

JOptionPane.showMessageDialog(new JFrame(), "两次输入密码不相同!", "错误",

JOptionPane.ERROR_MESSAGE);

password.setText("");

password2.setText("");

}

}

DB.java

public class UserDB {

// 驱动程序名

String driver = "com.mysql.jdbc.Driver";

// URL指向要访问的数据库名hello

String url = "jdbc:mysql://xxx:xxx/hello";

// MySQL配置

String sqluser = "root";

String sqlpassword = "xxx";

ClientThread.java

public ClientThread(Socket socket) {

try {

this.socket = socket;

reader = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

writer = new PrintWriter(socket.getOutputStream());

// 接收客户端的用户信息

String info = reader.readLine();

StringTokenizer st = new StringTokenizer(info, "@");

user = new User(st.nextToken(), st.nextToken());

// 反馈连接成功信息

// writer.println(user.getName() + user.getIp() + "与服务器连接成功!");

// writer.flush();

// 反馈当前在线用户信息

if (ServerUI.Clients.size() > 0) {

String temp = "";

for (int i = ServerUI.Clients.size() - 1; i >= 0; i--) {

temp += (ServerUI.Clients.get(i).getUser().getName() + "/" + ServerUI.Clients

.get(i).getUser().getIp())

+ "@";

}

writer.println("USERLIST@" + ServerUI.Clients.size() + "@"

+ temp);

writer.flush();

}

ServerThread.java

public void run() {

// 循环等待客户端的链接

while (true) {

try {

Socket socket = serverSocket.accept();

// 超过人数处理

if (ServerUI.Clients.size() >= max) {

BufferedReader read = new BufferedReader(

new InputStreamReader(socket.getInputStream()));

PrintWriter write = new PrintWriter(

socket.getOutputStream());


// 接收客户端的用户信息

String userInfo = read.readLine();

StringTokenizer st = new StringTokenizer(userInfo, "@");

User user = new User(st.nextToken(), st.nextToken());

// 反馈连接失败信息

write.println("MAX@亲爱的" + user.getName() + user.getIp()

+ ",服务器在线人数已达上限,请稍后连接!");

write.flush();

// 释放资源

read.close();

write.close();

socket.close();

continue;

}

ServerUI.java

public ServerUI() {

frame = new JFrame("欢迎来到聊天室!");

frame.setIconImage(new ImageIcon("image/icon.png").getImage());// 更改JFrame的图标

showMsg = new JTextArea();

showMsg.setEditable(false);// 显示消息框不可编辑

showMsg.setForeground(Color.red);

userSum = new Label("0 个在线用户");

txt_max = new JTextField("10");// 初始化人数

txt_port = new JTextField("6666");// 初始化端口


txt_msg = new JTextField();

txt_msg.setEnabled(false);

btn_send = new JButton("发送消息");

btn_send.setEnabled(false);

btn_start = new JButton("启动服务器");

btn_stop = new JButton("关闭服务器");

btn_stop.setEnabled(false);

listModel = new DefaultListModel();

userList = new JList(listModel);

northPanel = new JPanel();

northPanel.setLayout(new GridLayout(1, 6));

northPanel.setBorder(new TitledBorder("配置信息"));

northPanel.add(userSum);

northPanel.add(txt_max);

northPanel.add(new JLabel("个用户上限"));

northPanel.add(txt_port);

northPanel.add(new JLabel("端口"));

northPanel.add(btn_start);

northPanel.add(btn_stop);

leftPanel = new JScrollPane(userList);

leftPanel.setBorder(new TitledBorder("在线用户"));

rightPanel = new JScrollPane(showMsg);

rightPanel.setBorder(new TitledBorder("显示客户端消息"));

User.java

public class User {

private String name;

private String ip;


public User(String name, String ip) {

this.name = name;

this.ip = ip;

}


public void setName(String name) {

this.name = name;

}


public void setIp(String ip) {

this.ip = ip;

}


public String getName() {

return name;

}


public String getIp() {

return ip;

}

}

运行结果

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值