资源描述
密 级 公 开 学 号
XX学院
毕业设计
基于JAVA的即时通讯的设计与开发
论文作者
:
指导教师
:
系别
::
专业
计算机科学与技术
年级
:
提交日期
:
答辩日期
:
毕业论文(设计)学术承诺
本人郑重承诺:所呈交的毕业论文是本人在导师指导下进行的研究工作及取得的研究成果。除了文中特别加以标注和致谢的地方外,论文中不存在抄袭情况,论文中不包含其他人已经发表的研究成果,也不包含他人或其他教学机构取得的研究成果。
作者签名: 日 期:
毕业论文(设计)使用授权的说明
本人了解并遵守有关保留、使用毕业论文的规定。即:学校有权保留或向有关部门送交毕业论文的原件或复印件,允许论文被查阅和借阅;学校可以公开论文的全部或部分内容,可以采用影印、缩印或其他复制手段保存论文及相关资料。
作者签名: 指导教师签名:
日 期: 日 期:
基于JAVA的即时通讯的设计与开发
摘 要:即时通讯(Instant Messenger),是一种基于互联网的即时交流消息的业务,所常见的有: MSN、QQ、UC等。这些都具有很强的商业化特点。在现有网络基础上,研究一个安全的、私有的、本地或本部门化的即时通讯工具,非常有必要。Java是我们当前所使用的比较流行的开发语言,它有着自己简单易用的特点与性能优势(比如跨平台、安全性、多线程、网络Socket编程、数据流概念)。通过对即时通讯工具的需求、体系结构、构成模块等的分析和研究,采用java语言和eclipse为基本开发环境,应用重构开发方法,优化了系统设计,利用局域网通信机制的原理(即通过直接继承Thread类来建立多线程),实现了网络聊天服务器程序和网络聊天客户程序。前者通过Socket套接字建立服务器,使得服务器能读取并且转发客户端发来信息,同时还能刷新用户列表。后者通过与服务器建立连接,能够实现客户端与客户端的信息交流。
关键词:即时通讯;多线程;SOCKET编程;MySQL
III
DESIGN AND DEVELOPMENT OF A SIMPLE INSTANT COMMUNICATION TOOL BASED ON JAVA
Abstract: IM (Instant Messenger) is the business of an Internet-based real-time exchange of messages,for example : MSN, QQ, UC, and so on. These have a strong commercial characteristics. Researching on the basis of the existing network, a safe, private, local or sector of the instant messaging tools is very necessary. Java is currently much popular development language, it has its own easy-to-use features and performance advantages (such as cross-platform, security, multi-threaded, network socket programming, data flow concept). Through the analysis and study of the demand for instant messaging tools, architecture, building blocks, using java language and Eclipse as the basic development environment, the development of applications reconstruction method to optimize the system design, the use of the principle of local area network communication mechanism (through direct inherited thread class to create a multi-threaded), network chat server program and network chat client. The former socket to create the server so that the server can read and forward the information sent by the client, as well as refresh the user list. The latter through the connection with the server, the client and the client exchanging information.
Keywords: instant message; multithreaded; socket program; MySQL
目 录
摘 要 I
Abstract II
1引言 1
1.1项目开发的背景 1
1.2研究现状 1
1.3项目研究的内容 1
2相关理论及技术基础与开发平台 2
2.1即时通讯应用工作原理分析 2
2.2所用技术 2
2.3工具及开发平台 2
2.4 系统配置要求 3
3系统体系结构的设计 4
3.1 数据库的设计 4
3.2系统模块设计 4
3.2.1系统功能模块图: 5
3.3系统类设计 8
4系统实现 11
4.2 注册模块 11
4.2.1 流程图 11
4.2.2 关键代码 11
4.3 登录模块 13
4.3.1 流程图 13
4.3.2 关键代码 13
4.4 聊天模块 16
4.4.1 流程图 16
4.4.2 关键代码 16
4.5 文件模块 20
4.5.1 流程图 20
4.5.2 关键代码 20
4.6 用户管理模块 24
4.6.1 流程图 24
4.6.2 关键代码 24
4.7 用户界面的设计 26
结 论 29
致 谢 31
附录1 32
柳亚林:VLAN在校园网中的高效应用
级计算机科学与技术专业毕业论文
1引言
1.1项目开发的背景
我们的生活需要越来越方便、快捷的通讯工具。尽管当前有一些类似的工具,如:QQ、飞信等。这些软件属于公共性软件,安全性难言可靠。盗取用户账号进行网络诈骗和利用各种虚假中奖信息进行诈骗的事情屡见不鲜。如果某企事业单位内部为更便捷的交流,特别是当涉及较为敏感性话题时,显然这些软件还不能够适应这一需求。为此设计一个java的即时通讯。本系统包括服务器端和客户端,可以在企业内部网络和互联网上运行(主要是在企业内部)。同时本系统具有Java应用的跨平台特性,方便运行在各个系统之上。同时它具有比较漂亮的界面,与常用的qq有许多类似于功能(比如可以和好友进行在线交流、添加删除好友、即时发送、即时回复等功能)。
1.2研究现状
随着互联网得迅速发展,上网聊天已经成为人们生活中不可或缺的一部分,即时通讯也在不断更新发展。从最早的ICQ( I seek you)横空问世到现在的qq、msn等风靡全球,即时通讯也不过才走过了17个年头。功能从最早的只能发送文字到现在的可以发送邮件、语音、视频,即时通讯还有很大的发展空间。功能还在不断完善中以满足用户的需求。
1.3项目研究的内容
我们的生活需要越来越方便、快捷的通讯工具。最早它主要是作为一种聊天工具,目前其作用早已超出聊天的范畴。尽管当前有很多聊天工具,如:QQ、飞信等。这些软件属于公共性软件,安全性难言可靠。盗取用户账号进行网络诈骗和利用各种虚假中奖信息进行诈骗的事情屡见不鲜。如果某企事业单位内部为更便捷的交流,特别是当涉及较为敏感性话题时,显然这些软件还不能够适应这一需求。随着企业即时通讯工具的出现,即时信息将发挥更大的作用。为此设计一个java的即时通讯,以满足企事业单位内部的需求。
2相关理论及技术基础与开发平台
2.1即时通讯应用工作原理分析
TCP / IP和UDP(用户数据报协议)是我们平时比较熟知的,都是一种通信运输协议,建立在上下级IP协议。TCP / IP是数据流,数据的传输分割、包装、通过虚电路建立两台机器之间的、双向的、连续的、严格保证数据的正确性的文件传输协议。而UDP是以数据报的形式,对拆分后的数据的先后到达顺序不做要求的文件传输协议。我们常见的QQ就是使用UDP协议进行发送和接收消息的。
2.2所用技术
java网络编程中有两种不同的通讯协议,即TCP与UDP,两种协议各有优缺点。TCP是一种面向连接的保证可靠传输的协议。通过TCP协议的传输,能够得到一个顺序无差错的数据流。UDP是一种无连接的协议,每个数据报都是一个独立的信息,在网络上它以任何可能的路径传往目的地,因此不能被保证能否到达目的地,也不能保证内容的正确性。
SWING界面设计:用来实现客服端的界面设计。Swing是一个用于开发Java应用程序用户界面的开发工具包。囊括丰富的控件操作功能以及众多的控件,使户可以简单的利用它结合JBuilder9.0带的绝对定位类包,可以设计出非常好看的用户界面。
JSP与SERVLET技术:JSP和SERVLET是在j2ee平台下开发的一种WEB应用的基础,JSP技术可以快速开发出与平台无关的基于WEB的应用,为建立具有动态生成内容的WEB应用提供了一种简便而且功能强大的途径,JSP是更高级的SERVLET,在运行的时候JSP先被转化为SERVLET。
2.3工具及开发平台
客户端采用C/S结构,管理端采用B/S的结构,用Tomcat 作为服务器,MySQL作为数据库。
用过对C/S结构的使用,能充分发挥客户端PC的处理能力,使得许多工作能够在客户端处理后再提交给服务器。所对应的优点就是客户端响应速度快。缺点则有对客户端的操作系统也会有限制和远程访问需要专门的技术, 这种技术要求极大的工作量,而且一旦出现问题,整个系统都要进行维修。
SQL SERVER2000数据库具备很多数据库管理常用的功能,是微软的功能强大的数据库管理系统,是一个非常理想的后台数据库系统。
Tomcat是一个免费的开源的Serlvet容器,是Sun的JSWDK(JavaServer Web Development Kit)中Servlet的运行环境。
2.4 系统配置要求
推荐配置如下:服务器端要安装Sql server2000数据库, 服务器端如果是windowsXP系统要打上Sql server 2000的SP3或者SP4补丁包。服务器端还需要安装Web服务器TOMCAT, myeclipse6.5。运行平台基于Windows平台。 客户端需要安装java虚拟机。
3系统体系结构的设计
3.1 数据库的设计
本系统中所涉及的主要实体及其属性有:
用户(用户账号,用户名,密码,个性签名,头像ID,年龄,性别)
E-R模型如图所示。
图 3-1系统实体及其属性
表3-1 User
字段名
数据类型
字段说明
键引用
备注
account
int(6)
ID
PK
主键(自动增一)
name
varchar(20)
用户名称
非空
password
varchar(20)
用户密码
非空
signature
Varchar(255)
签名
profileID
int(2)
头像ID
age
int(3)
年龄
sex
sex char(2)
性别
3.2系统模块设计
3.2.1聊天系统工作原理图
图 3-2 系统工作原理
3.2.2系统功能模块图:
图 3-3 系统模块
图 3-4 普通用户用例图
后台管理员的用例图:
图 3-5 后台用户用例图
3.2.3活动图:
1)用户登陆活动图
首先填写登陆信息,提交以后服务器会对用户名和密码进行验证。如果不正确,返回一个提示信息。如果登陆成功,就更新在线状态。通知所有好友自己已经上线。服务器再检查是否有他的离线消息,如果有这立即发送给用户。
图 3-6 用户登录活动图
2)发送消息活动图
短消息发送以后,服务器端对应的监听线程会接收到一个数据包。此包中包含接收者的信息,如果接收者在线,数据包将会转发到接收者。如果不在线,存在服务器端,等它上线在发送。
图 3-7发送消息活动图
3.3系统类设计
3.3.1 Message类的设计:
客户端和服务器端通信时,发送的都是Message类的对象,因此Message类的设计很重要。
表4-2 Message
属性名
作用
private Integer msgType;
信息类型
private String content;
信息的文本内容
private Integer senderAccount;
发送者account
private Integer receiverAccount;
接收者account
private String time;
发送时间
private User myself;
private List<User> friends;
自己本身对象,用与好友列表头
好友列表
private transient Image img;
图片对象(不传送)
private byte[] imageByte;
图片的内容
private String fileName;
文件名称
private byte[] fileByte;
文件的长度
private int length;//文件长度,以KB为单位
文件的内容
private int state;
文件传输的状态:0是不接受文件,1是接受文件,2请求发送文件,3文件传输中,4文件传送完成
private Integer msgType消息的类型有这么几种:
public interface MessageType {
Integer message_succeed=1;//表明是登陆成功
Integer message_login_fail=2;//表明登录失败
Integer message_comm_mes=3;//普通信息包
Integer message_get_onLineFriend=4;//要求在线好友的包
Integer message_ret_onLineFriend=5;//返回在线好友的包
Integer message_offline=6;//下线通知包
Integer message_img=7;//图片包
Integer message_file=8;//文件包
}
3.3.2服务端线程的设计:
服务器端的核心是对应客户的线程,每个socket对应一个线程,也就是每一个客户端都在服务器端有一个相应的线程。它负责转发客户端发来的消息。线程类为ClientThread:
表4-3 ClientThread类
属性名
作用
public void notifyOnline()
通知其他线程,自己上线了,让客户方更新头像
public void run()
线程的主题,转发消息
public void notifyOffline(){
通知其他线程,自己下线了,让客户方更新头像
public void send(Object o)
发送消息
public Object receive()
接收消息
4系统实现
4.1 实现概况
本系统可分为登录、聊天、文件、用户管理和注册五个功能模块。“登录”模块为用户提供登录界面,并在用户登录显示好友列表;“聊天”模块实现用户的即时传送信息,即多用户即时聊天,可以发送文字或者截图;“文件”模块主要实现一用户向另一用户发送文件,对方可以选择接受或者拒绝。聊天记录会以文本文档格式保存。“用户管理”模块即管理员对用户进行增删改查,和踢用户下线的操作。
下面详细介绍各个模块的具体实现。
4.2 注册模块
4.2.1 流程图
图4-1用户注册流程图
4.2.2 关键代码
注册的前台页面是showDetail.jsp,后台是UserAction类,UserAction类中有方法:
public String saveOrUpdate(){
us.saveOrUpdate(user);
return "refresh";
}
saveOrUpdate则是用到了Userservice里面的方法:
public void saveOrUpdate(User u){
System.out.println("u.getAccount()="+u.getAccount());
if(u.getAccount()==null)
ud.save(u);
else ud.update(u);
}
DAO类中的方法:
public void save(User u){
conn=getConnection();
try {
ps=conn.prepareStatement(SAVE);
ps.setString(1, u.getName());
ps.setString(2, u.getPassword());
ps.setString(3, u.getSignature());
ps.setInt(4, 1);
ps.setInt(5, u.getAge());
ps.setString(6, u.getSex());
ps.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
close();
}
}
网页上显示用户的account
图 4-2 用户注册信息
4.3 登录模块
4.3.1 流程图
图 4-3 登录流程图
4.3.2 关键代码
1)客户端代码
登录事件是定义在class IMClientLogin extends JFrame 这个类的监听事件中。登录成功后,立即向服务器请求自己的好友列表。
//登录事件
login.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// cus=new IMClientUserServer();
// System.out.println(cus.getServer());
User u=new User();
u.setAccount(Integer.parseInt(account.getText().trim()));
u.setPassword(new String(passwordField.getPassword()));
// 登陆成功
if(cus.checkLogin(u)){
//向服务器发送数据包,请求在线人得信息
ClientConnToServerThread t=Manager.THREAD;
Message m=new Message();
m.setMsgType(MessageType.message_get_onLineFriend);
m.setSenderAccount(u.getAccount());
try {
t.send(m);
} catch (IOException e1) {
e1.printStackTrace();
}
dispose();
}
else
JOptionPane.showMessageDialog(null, "用户名或密码错误", "错误", JOptionPane.ERROR_MESSAGE);
}
});
登录逻辑是在public class IMClientUserServer 里面,认证成功者就会新建一个线程,专门负责接收服务器端发来的信息class ClientConnToServerThread extends Thread 。
public boolean checkLogin(Object o) {
boolean success=false;
Message msg=(Message) server.sendLoginInfo(o);
// System.out.println(msg.getMsgType());
// System.out.println(MessageType.message_succeed);
if(msg.getMsgType().intValue()==MessageType.message_succeed.intValue()){
success=true;
User u=(User) o;
//将好友列表放到管理器中,进行上下线操作
IMFriendList fl=new IMFriendList(msg.getMyself(),msg.getFriends());
Manager.FRIEND_LIST=fl;
//开启客户线程 ,接收服务器端的信息
connThread =new ClientConnToServerThread(server.getSocket());
connThread.setSocket(server.getSocket());
connThread.start();
connThread.setName(u.getAccount()+"");
Manager.THREAD=connThread;
}
return success;
}
客户端通过public class IMClientServer 类与服务器通信
public Object sendLoginInfo(Object o) {
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(o);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message ms = (Message) ois.readObject();
return ms;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
这样按照MVC的模式设计,减小的系统耦合。
2)服务端代码
服务器端接收用户验证信息的代码被写在了一个线程public class ServerThread extends Thread中,这样服务器就可以不停的监听端口,接收来自不同客户端的请求,建立socket连接,也不会堵塞在主线程当中。
从数据库中搜索用户,看是否存在
public boolean checkLogin(User u){
User user=ud.findById(u.getAccount());
if(user!=null){
return user.getPassword().equals(u.getPassword());
}
return false;
}
如果验证成功,查找是否有他的离线消息,有就发送给他。然后在服务器上专门开启一个针对当前用户的线程,并且吧线程放入管理类中,便于日后的管理。
if (checkLogin(u)) {
// 返回一个成功登陆的信息报
User myself=ud.findById(u.getAccount());
m.setMsgType(MessageType.message_succeed);
m.setMyself(myself);
m.setFriends(ud.findAll());//好友列表
oos.writeObject(m);
//为用户单独创建线程
ClientThread t=new ClientThread(s);
//查看是否有离线消息
LinkedList<Message> list=OffLineMsgManager.get(u.getAccount());
if(list!=null){
for(Message msg:list){
t.send(msg);
}
list.clear();
}
//开启线程
t.start();
t.setName(u.getAccount()+"");
//把用户线程放入管理类中
ClientThreadManager.addClientThread(u.getAccount(), t);
//通知其他的用户
t.notifyOnline();
System.out.println(" 成功");
} else {
m.setMsgType(3);
oos.writeObject(m);
System.out.println(" 失败");
// 关闭Socket
s.close();
}
4.4 聊天模块
4.4.1 流程图
图 4-4 聊天流程图
4.4.2 关键代码
1)客服端代码
发送文字信息:
客户端发送和显示信息的代码被封装在了IMChat extends JFrame implements ActionListener类中,其中发送文字信息的代码
//点击的如果是发送button
if (e.getSource() == confirmButton) {
Message m=(Message) makePackage(MessageType.message_comm_mes,null);
//发送
sendMessage(m);
//在自己的Ouput上显示
showMessage(m,Color.BLACK);
//清空输入
input_textArea.setText("");
}
当用户点击发送按钮后,先把先把信息显示在自己的聊天窗口上,后方发送信息,自己发送的信息和接收到的信息用不同的颜色显示。
显示文字信息,显示在JtextPane控件中
SimpleAttributeSet attrset = new SimpleAttributeSet();
StyleConstants.setForeground(attrset,c);
Document docs = output_pane.getDocument();
// 利用getDocument()方法取得JTextPane的Document
//一般信息
if(m.getMsgType().intValue()==MessageType.message_comm_mes){
String str=m.getSenderAccount() + " " +m.getTime()+"\n"+" "+ m.getContent()+ "\n";
try {
docs.insertString(docs.getLength(), str, attrset);
//设置光标到末尾
output_pane.setCaretPosition(docs.getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
发送图片信息:
在发送图片信息的时候,先将图片转换成为byte[]数组,包装在信息包种发送出去,接收到图片信息时,从byte[]数组构建图片,显示出来。
图片和byte[]之间相互转换的关键代码如下:
//将image转换成 byte[]
public byte[] imageToBytes(Image img){
ByteArrayOutputStream bos=new ByteArrayOutputStream();
try {
ImageIO.write((RenderedImage) img, "jpg", bos);
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
//将 byte[]转换成image
public Image bytesToImage(byte[] b){
try {
return ImageIO.read(new ByteArrayInputStream(b));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
在JtextPane中显示图片的代码:
if(m.getMsgType().intValue()==MessageType.message_img){
//图片信息
String str=m.getSenderAccount() + " " +m.getTime()+ "\n";
try {
//显示发送人 和时间
docs.insertString(docs.getLength(), str, attrset);
//设置光标到末尾
output_pane.setCaretPosition(docs.getLength());
output_pane.insertIcon(new ImageIcon(m.getImg()));
docs.insertString(docs.getLength(), "\n", attrset);
//设置光标到末尾
output_pane.setCaretPosition(docs.getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
在客户端显示截图示例:
图 4-5 聊天截图
2)服务端代码
服务端接收到客户端的信息后,只需要根据他的接收人,进行转发就可以。关键代码如下:
Message m = (Message) receive();
// 如果是普通信息
if (m.getMsgType() == MessageType.message_comm_mes.intValue()) {
System.out.println(m.getSenderAccount() + "send to"+ m.getReceiverAccount() + "at" + m.getTime());
Integer receiverAccount = m.getReceiverAccount();
ClientThread t = ClientThreadManager.getClientThread(receiverAccount);
if (t == null) {
//不在线就暂时存储在服务器上
OffLineMsgManager.putSingle(receiverAccount, m);
} else
t.send(m);
4.5 文件模块
4.5.1 流程图
图 4-6 发送文件流程图
4.5.2 关键代码
1)客户端代码
在客户端采用JfileChooser来浏览本地文件,点击浏览按钮后,会弹出对话框,让用户选择文件,然后将文件名,大小等信息封装在数据包里,发送出去。关键代码如下:
@Override
public void mouseClicked(MouseEvent e) {
fileDialog.setDialogTitle("选择文件");
fileDialog.showOpenDialog(IMChat.this);
//只能选中文件
fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY);
f=fileDialog.getSelectedFile();
//发送数据包,请求发送文件
Message m = new Message()
展开阅读全文