在这个版本已经实现了基本的聊天,群聊以及文件发送功能.
为了图简单,只要是在线的用户就都会出现在所有客户端列表中,没有单独为每个用户保存好友,群聊所有人都会收到消息.
注册的用户信息都保存在文件中,每次服务器启动就先读取数据.
客户端连接上之后,就给所有在线的其他客户端发送自己上线的消息,然后其他客户端就更新好友列表.
双击即可打开对话窗口进行聊天或者传文件.
界面演示图:
之前两个版本:
第一版:
http://479001499.iteye.com/blog/2100893
第二版:
http://479001499.iteye.com/blog/2101491
这个版本在第二版之上改进的功能:
增加头像设置,文件传输.
在User类中增加一个属性,String 用来保存图片路径.设置头像实际为设置String的值.然后再生成ImageIcon.
if (source.equals("头像")) { System.out.println("点击了更换头像"); JFileChooser jfc = new JFileChooser("images\\"); int state = jfc.showOpenDialog(MyInfo.this); if (state == 0) { user.headIcon = jfc.getSelectedFile().getAbsolutePath(); head.setIcon(new ImageIcon(user.headIcon)); // 将这个消息传至服务器 Message msg = new Message(); msg.type = MessageUtil.ChangeInfo; msg.senderNum = user.num; msg.receiverNum = 2;// 所有人加上服务器都要接受并修改信息 msg.content = user; try { MessageUtil.send(os, msg); } catch (Exception ee) { ee.printStackTrace(); } } }
修改之后,像所有客户端发送消息,让他们更新消息:
if (msg.type == MessageUtil.ChangeInfo) { System.out.println("接受到用户修改信息"); // 标记修改了信息,当这个为true的时候.再打开对话窗口就需要更新其头像,否则再打开就只需要setVisible havaChanged = true; User us = (User) msg.content; String olaNik = map.get(msg.senderNum).name; // 将map<账号,昵称>中的元素进行修改 mapN2N.remove(olaNik); ChatAllUI.dlm.removeElement(olaNik); // 将map<昵称,账号>中的元素进行修改 mapN2N.put(us.name, msg.senderNum); ChatAllUI.dlm.addElement(us.name); map.put(msg.senderNum, us); // 更新各个地方的显示 if (us.num == user.num) { nik.setText(user.name); textField_1.setText(user.qianming); dlm.set(0, user.name); } else { int temp = dlm.indexOf(olaNik); dlm.removeElement(olaNik); dlm.add(temp, us.name); } }
在原有基础上增加一个文件收发的工具类FileTransfer,用来从文件中读取数据和保存数据到文件.
package v140813; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class FileTransfer { /** * 文件发送 * * @param os * 输出流 * @param file * 文件 */ public static void fileSend(OutputStream os, File file) { try { FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(os); int t = bis.read(); while (t != -1) { bos.write(t); t = bis.read(); } bos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 收到了开始接收文件的消息里面的内容为文件名,保存在fileRec 目录下 * * @param is * 输入流 * @param fileName * 文件名 * @param size * 文件大小 * @param num * 接收者的num */ public static void fileReceive(InputStream is, String fileName, long size, int num) { File f = new File("fileRec\\" + num + "\\"); if (!f.exists()) { f.mkdir(); } File file = new File("fileRec\\" + num + "\\" + fileName); try { BufferedInputStream bis = new BufferedInputStream(is); FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos); for (long i = 0; i < size; i++) { int t = bis.read(); // System.out.println(t); bos.write(t); } bos.flush(); System.out.println("接收完毕"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
客户端这边,发送文件之前,首先向服务器发送一条消息,内容为文件名和文件大小.
服务器启动一个线程接收文件,在线程中需要将输入流锁起.
服务器收完文件之后,再向接收文件的客户端发送一条消息,内容为文件名和文件大小
同样,客户端开始接收文件.接收完毕之后,向发送者发出消息说已经接收了文件.
public class ReceiveFileThread extends Thread { String fileName; long size; public ReceiveFileThread(String content) { String contents[] = content.split("#"); this.fileName = contents[0]; size = Long.parseLong(contents[1]); System.out.println("准备接收 文件大小:" + size); } public void run() { try { synchronized (is) { FileTransfer.fileReceive(is, fileName, size); } System.out.println("接收完毕"); } catch (Exception e) { e.printStackTrace(); } } } /** * 发送文件的线程 * * @author Huangbin * */ class SendFileThread extends Thread { File file; OutputStream os; String content; int receiverNum; public SendFileThread(File file, int receiverNum, String content) { this.file = file; this.os = Server.slist.get(receiverNum).os; this.content = content; this.receiverNum = receiverNum; } public void run() { synchronized (os) { try { MessageUtil.send(os, new Message(8, num, receiverNum, content)); System.out.println("准备发送"); // 开始发送 System.out.println("开始发送"); FileTransfer.fileSend(os, file); System.out.println("发送完毕"); } catch (Exception e) { e.printStackTrace(); } } } }
(这里的接收文件线程和发送文件线程可有可无,因为流只有一个,传文件同时就不能传消息,有没有线程都一样的,初步预计的解决办法是传文件的时候再和服务器建立一个单独的连接,专门用来文件的传输,这样就不会因为只有一个流而不能同时工作了.)
接收客户端的处理:
if (msg.type == MessageUtil.FileTransfer) { String fileName = ((String) msg.content) .split("#")[0]; if (pcMap.containsKey(msg.senderNum)) { // 消息中的发送者在我这边是待会儿的接收者 pcMap.get(msg.senderNum).textArea .append(map.get(msg.senderNum).name + " 给你发送了一个文件" + msg.content + "\r\n"); } else { ChatOneUI coui = new ChatOneUI(os, is, num, msg.senderNum, map); coui.textArea .append(map.get(msg.senderNum).name + " 给你发送了一个文件: " + fileName + "\r\n"); pcMap.put(msg.senderNum, coui); } System.out.println(msg.content); ReceiveFileThread rft = new ReceiveFileThread( (String) msg.content); rft.start(); // 给线程缓冲时间,不然这个接收消息的线程又去读取消息去了 while (rft.isAlive()) { } // 接收完毕了,发送消息给对方告诉他已经收到了 pcMap.get(msg.senderNum).textArea .append("接收完毕。"); MessageUtil.send(os, new Message( MessageUtil.ONEUSER, num, msg.senderNum, "已经接收了你发送的文件: " + fileName + "\r\n")); }
附上所有的代码:(图片素材在第二版里面,将images文件夹放到ChatClient文件夹下)
客户端每个包下都有一个说明文件,里面说明了这个包在上一个包的基础上进行了一些什么修改
相关推荐
仿QQ聊天系统课程设计
这是我们JAVA课程,网络、多线程实验程序,为类QQ聊天程序,支持点对点文件传输。
NULL 博文链接:https://479001499.iteye.com/blog/2115971
仿QQ聊天软件源代码java版仿QQ聊天软件源代码java版
使用javasocket技术模仿QQ的聊天软件 实现了添加好友 删除好友 群聊天 上传文件等功能
使用MFC SOCKET编程开发了基于C/S架构的一个仿QQ聊天系统,客户端间可以互通消息,传输文件等。适合学习C++ Socket编程,文件传输,多线程,线程和进程间通信等,适用于课程设计或学期作业等环境
vb 仿QQ聊天程序
仿QQ聊天系统,运用技术java swing,其中用到了大量的线程,socket,特别适合j2se的初学者!内含数据库
仿qq聊天工具
仿QQ聊天记录
本软件是仿QQ聊天工具
仿QQ聊天系统源码,仿QQ聊天系统是基于MySQL数据库开发工具进行设计,理论研究与实践相结合,利用计算机技术、数据库技术,java技术等对腾讯QQ聊天系统的开发设计进行研究以JAVA技术为核心,利用计算机局域网通信机制...
仿QQ聊天,带服务端和客户端,可文字聊天和语音聊天,支持发送文件
这是一个仿QQ的多人聊天室,用到Java SE中的Socket进行连接
qq聊天系统源码 仿qq聊天系统源码 asp.net仿qq聊天系统源码
仿QQ界面,实现界面,实现聊天对话框界面风格
类似qq聊天界面,css书写,jq写入包含消息收发、文件收发、加密会话、阅后即焚等功能界面。界面简单适用
内含完整聊天程序 类似QQ 是应用与学习的好模板 字体设置 头像选择 文件传输 QQ秀上传等
Java仿QQ聊天程序源代码 HAHA CHAT Java仿QQ聊天程序...这个聊天程序有着QQ一样的隐藏窗体,程序有服务端和QQ登录端,同时还有一些设置程序,虽然窗口没有现在的QQ漂亮,但是用Java写出来我觉得挺难得了,奉献给大家 。