一、项目简介
功能描述:实现了使用Sockect简易的聊天室功能,用Swing和awt进行客户端聊天,登录,注册界面的图形化,用MYSQL数据库实现了用户信息存储。用户可向指定的用户发送信息
二、功能架构图或主要功能流程图
三、个人任务简述
1. 完成的任务与功能
以表格形式描述将自己完成的有特色的地方、重难点地方。
序号 | 完成功能与任务 | 描述 |
1 | 聊天服务器搭建 | 使用Serversocket进行服务器的搭建 |
2 | 聊天客户端搭建 | 使用了面向对象技术设计系统。 |
3 | 服务器与客户端交互 | 客户端与服务器根据一定的规范进行信息交互 |
4 | 登录注册功能 | 使用了DAO模式。使用了MYSQL数据库 |
5 | 数据库设计 | 采用MySQL数据库。表设计符合第三范式。 |
2. Git提交记录截图:
四、本人负责功能详解
1.面向对象设计
聊天室的设计,进入聊天室时需要先登录或注册,考虑到聊天时需要显示在线的用户,和对多个在线的用户进行聊天。Server类提供端口监听,把SeverThread分配给客户端,ServerThread类实现对Client客户端的交互提供向聊天服务。
2.聊天客户端搭建
客户端更新自己的在线用户列表,通过服务器的content确定需更新的在线列表
服务器消息例子:OnlineListUpdate/小猫&192.168.125.15:52140,小高&192.168.125.15:52155
private static void OnlineListUpdate(String content,ClientFrame cframe) throws UnknownHostException {
DefaultTableModel tbm = (DefaultTableModel) cframe.jtbOnline.getModel();
tbm.setRowCount(0);
String[] onlinelist = content.split(",");
for(String member : onlinelist)
{
String[] tmp = new String[3];
if(member.substring(member.indexOf("&")+1).equals(InetAddress.getLocalHost().getHostAddress() + ":" + s.getLocalPort()))
continue;
tmp[0] = member.substring(0,member.indexOf("&"));
tmp[1] = member.substring(member.indexOf("&")+1, member.indexOf(":"));
tmp[2] = member.substring(member.indexOf(":") + 1);
tbm.addRow(tmp);
}
DefaultTableCellRenderer tbr = new DefaultTableCellRenderer();
tbr.setHorizontalAlignment(JLabel.CENTER);
cframe.jtbOnline.setDefaultRenderer(Object.class, tbr);
}
客户端更新自己的聊天框,通过服务器的content确定需更新的聊天框信息
服务器消息例子:Chat/小高&192.168.125.15:52155/你好小猫
private static void Chat(String content,ClientFrame cframe) {
System.out.println(content);
String name=content.substring(0,content.indexOf("&"));
String sender = content.substring(content.indexOf("&")+1, content.indexOf("/"));
String word = content.substring(content.indexOf("/") + 1);
cframe.jtaChat.append(cframe.sdf.format(new Date()) + " \n来自 " + name + ":" + word + " \n");
cframe.jtaChat.setCaretPosition(cframe.jtaChat.getDocument().getLength());
}
3.聊天服务器搭建
String ip = null;
int port = 0;
String uid = null;
static ArrayList<String> uid_arr = new ArrayList<String>();
static HashMap<String, ServerThread> hm = new HashMap<String, ServerThread>();
static HashMap<String,String> hm2=new HashMap<>();
public ServerThread(Socket s, ServerSocket ss, String ip, int port)
{
this.s = s;
this.ss = ss;
this.ip = ip;
this.port = port;
uid = ip + ":" + port;
}
服务器通过ServerSocket监听,ServerThread为请求连接的客户端分配线程,uid为IP+":"+端口,将线程放进uid_arr中,hm将线程与uid名对应起来,hm2将uid于网名对应起来
当服务器监听到一个连接后或一个客户端断开连接后,向客户端发送在线列表的更新
public void updateOnlineList(OutputStream out) throws Exception
{
for(String tmp_uid : uid_arr)
{
out = hm.get(tmp_uid).s.getOutputStream();
StringBuilder sb = new StringBuilder("OnlineListUpdate/");
for(String member : uid_arr)
{ String name=hm2.get(member);
sb.append(name+"&"+member);
if(uid_arr.indexOf(member) != uid_arr.size() - 1) {
sb.append(",");
}
}
out.write(sb.toString().getBytes());
}
}
当服务器接收到客户端聊天请求时,向客户端指定的用户发送聊天内容
public void chatOnlineList(OutputStream out, String uid, String[] receiver_arr, String word) throws Exception
{
for(String tmp_uid : receiver_arr)
{
out = hm.get(tmp_uid).s.getOutputStream();
String name=hm2.get(uid);
out.write(("Chat/" +name+"&"+ uid + "/" + word).getBytes());
}
}
4.登录和注册
通过JDBC与数据库交互判断是否登录成功,成功后进入聊天界面,以及注册时用户名有无重复
String pwd = new String(password.getPassword());
if(udji.validatePassword(user.getText(), pwd)){
//登录成功,登录界面不可见
jFrame.setVisible(false);
Client.name= user.getName();
try {
OutputStream os=s.getOutputStream();
os.write(("Name/"+user.getText()+"&"+myUid).getBytes());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
cframe.setVisible(true);
}else{
//用户名错误
JOptionPane.showMessageDialog(jFrame,"用户名错误或密码错误","提示",JOptionPane.INFORMATION_MESSAGE);
//将用户名和密码置空
user.setText("");
password.setText("");
}
if (username == null || "".equals(username)) {
JOptionPane.showMessageDialog(contentPane, "请输入账号", "系统提示", JOptionPane.WARNING_MESSAGE);
} else if (password == null || "".equals(password)) {
JOptionPane.showMessageDialog(contentPane, "请输入密码", "系统提示", JOptionPane.WARNING_MESSAGE);
//检查用户名是否重
} else if (udji.getUserByName(username)==false) {
if (username.isEmpty() && password.isEmpty()) {
JOptionPane.showMessageDialog(null, "请输入用户名和密码!", "提示消息", JOptionPane.WARNING_MESSAGE);
} else {
udji.writeUser(username,password);
JOptionPane.showMessageDialog(null, "注册成功!", "提示消息", JOptionPane.WARNING_MESSAGE);
dispose();
}
} else {
JOptionPane.showMessageDialog(contentPane, "用户名已存在", "系统提示", JOptionPane.WARNING_MESSAGE);
usernameText.setText("");
passwordText.setText("");
}
五、运行截图
六、课程设计总结及展望
总结:深入学习了Java网络编程的相关知识,掌握了TCP协议的工作原理以及如何在Java中实现Socket通信。我们还学习了多线程编程,使聊天室能够同时处理多个客户端连接。
展望:没有实现文件传输的功能。聊天室的功能比较简单,没有考虑用户界面的美观。在设计过程中,我们没有考虑到安全性问题,例如数据加密等。
七、课程设计感想
在实现聊天室功能的过程中,我遇到了许多困难和挑战。如何实现多用户同时在线聊天、如何处理各种异常情况等。通过不断尝试和调整,我逐渐找到了解决问题的方法,这让我非常有成就感。
八、参考文献
黑马程序员Java零基础视频教程_下部(Java入门,含斯坦福大学练习题+力扣算法题和大厂java面试题)