JAVA语言课程设计报告
题 目:Java聊天室 设 计 者: 郭旭 专业班级: 学 号: 指导教师:
2010年12月30日
1.系统需求分析
1.1系统名称: Java聊天室 1.2系统介绍
该系统采用了线程及socket通信技术,使用了Java的图像化界面工具swing,在eclipse开发工具中进行开发。该系统的开发时给予C/S的架构,由客户端与服务器端进行通信,并且在服务器端进行逻辑判断和处理。该系统主要包括登录、注册、添加和删除好友、聊天、查找好友、文件传输等功能模块。
主要用到的技术:Java的图像化开发Swing ,Socket进程通信,Java线程技开发使用的工具:Eclipse中安装swing插件,数据库使用了MySql,并且使用了Navicat实现数据库的可视化操作。
运行环境:该系统以jdk1.6.0_10版本JDK为Java运行环境。 1.3开发背景
在即时聊天工具的出现之前,e-mail一直做为传统的信息交流工具,也是因为e-mail发送和接受消息时间相对滞后的缘故,不能满足人们迅速获取信息的要求。即时通讯工具的产生,为大众提供了一种崭新的综合的信息交流平台。即时通讯不同于传统的通讯工具e-mail,在于它的交流是实时的,使得人们交流更加便捷和快速,满足了人们迅速获取信息的需求,所以深受大众的喜爱,有着很好的发展前景。其中聊天软件就是即时通讯的具体实现。
本系统是一款普通的网络聊天工具,该软件主要有一对一聊天,一对多聊天,文件的传输,信息的保存等功能。系统是基于TCP/IP的网络协议,使用Java Socket进行通信,用现在最流行的网络开发语言Java进行编写实现。 术,Java的输入输出流IO等。
2.系统总体设计
总体结构:使用了典型的C/S架构,如下所示:
客户端 服务端 客户端 3.系统详细设计
3.1数据库设计: 用户表User: 列明 Username Nickname Password Gender Age City Online 好友表Friend: 列明 Id username Friendname 3.2页面设计 3.2.1:登录页面:
用户在登录页面,可以输入用户名和密码进入系统,当然,若用户输入的用户名和密码不正确,系统会给出提示,新用户也可以通过该页面链接到注册页面进行注册,然后回到该页面进行登录
3.2.2:注册页面:
用户在登录页面可以直接登录系统,若是新用户没有登录信息,则会被引导到该页面进行注册,注册新用户时,需要安装一定的规则输入用户信息,有必填项,以及相应的验证。
类型 int varchar varchar 长度 8 32 32 是否为主键 是 外键 外键 描述 标识id 用户名 用户名(好友) 类型 varchar varchar varchar char int varchar char 长度 32 32 32 1 4 32 1 是否为主键 是 描述 用户名 昵称 密码 性别:缺省0 男 年龄 城市 是否在线:缺省0 离线
3.2.3,登录成功后的用户主页面:
用户登录成功之后,在用户的主界面会显示出用户的好友列表等信息,同时也会显示出该用户的好友是否在线等信息。
右键单击用户:
搜索用户,并可以通过该页面添加好友,页面如下:
查看资料:
点击聊天室,可以实现群聊:
3.2.4、服务器端代码: Server.java
package mainserver;
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; /**
* 服务器主线程,负责接收客户端连接,并开启相应线程 响应 *
* 服务器的事务: 0,主线程,负责接收客户端连接,并开启相应线程 响应登陆用户请求 *
* 1,定时检测连接状态,并修改相应的用户状态,如果连接关闭(非正常关闭,例如 网络故障导致;而登陆用户正常退出由子线程负责处理状态的修改。),则 * 将相应用户的状态设为未登陆,以保证同一时刻一个用户只能 登陆一次。 PS:由于主线程无法很好的监控各套接字的状态,因此1该为在子线程中处理 *
* @author Administrator * */
public class Server {
/**
* 服务器参数初始化
private static final int SERVER_PORT = 9999;
public static Map private boolean running; ServiceHandler>(); */ private void init() { } public Server() { } /** * 服务器开启 */ public void start() { } init(); try { } startServer(); while (running) { } Socket socket = null; try { } System.out.println(\"Listenning... ...\"); socket = serverSocket.accept(); System.out.println(socket.getRemoteSocketAddress()); new ServiceHandler(socket).start(); e.printStackTrace(); serverSocket = new ServerSocket(SERVER_PORT); System.out.println(\"ServerSocket建立失败\"); e.printStackTrace(); return; } catch (IOException e) { } catch (IOException e) { } public void closeServer() { } private void startServer() { } public boolean isRunning() { } return running; running = true; running = false; System.exit(0); ServiceHandler.java package mainserver; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.util.Arrays; import java.util.Iterator; import java.util.List; import messages.AddFriend; import messages.DelFriend; import messages.Friends; import messages.Info; import messages.Login; import messages.MessageEnd; import messages.Regist; import messages.SearchFriend; import messages.Send; import messages.Update; import dao.Friend; import dao.FriendDAO; import dao.User; import dao.UserDAO; /** * 处理单个客户端请求的线程 如果socket读取或发送数据失败,按用户退出登陆处理 * * @author Administrator * */ public class ServiceHandler extends Thread { public ServiceHandler(Socket socket) { this.socket = socket; isOK = true; try { } try { in = new BufferedReader(new InputStreamReader(socket .getInputStream())); out = socket.getOutputStream(); e.printStackTrace(); isOK = false; return; } catch (IOException e) { private Socket socket; private BufferedReader in; private OutputStream out; private boolean isOK; private String currentUser; } catch (IOException e) { e.printStackTrace(); isOK = false; } /** } * 向客户端发送数据 如果发送失败,修改用户状态为未登录 * * @param msg */ public synchronized void send(String msg) { } private synchronized String read() { } String tmp = null; try { } if (tmp != null) { } return null; return tmp; tmp = in.readLine(); e.printStackTrace(); userQuit(); } catch (IOException e) { if (!isOK) { } try { } System.out.println(\"send: \" + msg); // ShowErrorMsg.display(msg); out.write(msg.getBytes()); out.flush(); userQuit(); return; } catch (IOException e) { /** * 如果读取失败,修改用户状态为未登录 从客户端读取数据 * * @param socket */ private String receiveTitle() { StringBuffer buffer = new StringBuffer(); if (!isOK) { } String tmp = null; try { if ((tmp = in.readLine()) != null) { return buffer.toString(); } } else { } new UserDAO().setOnline(this.currentUser, b); synchronized (Server.connections) { } Server.connections.remove(this.currentUser); /** * 发送或接收数据失败,修改用户状态 * * @param b */ private void changeUserState(boolean b) { // 设定为上线 if (b) { synchronized (Server.connections) { } Server.connections.put(this.currentUser, this); } } } buffer.append(tmp); } catch (IOException e) { userQuit(); return buffer.toString(); return buffer.toString(); private void userQuit() { } public void run() { while (isOK) { String title = this.receiveTitle(); if (title != null && title.length()!=0) { if (title.equals(Login.title)) { System.out.println(\"get: \" + Login.title); System.out.println(this.read()); loginHandle(); this.read(); addFriendHandler(); this.read(); friendsHandler(); this.read(); registHandler(); this.read(); System.out.println(\"失去一个连接。\"); isOK = false; changeUserState(false); } else if (title.equals(AddFriend.title)) { } else if (title.equals(Friends.title)) { } else if (title.equals(Regist.title)) { } else if (title.equals(SearchFriend.title)) { } } } } searchFriendHandler(); int id = Integer.parseInt(this.read()); sendHandler(id); this.read(); updateHandler(); this.read(); infoHandler(); this.read(); delFriendHandler(); System.out.println(\"nothing catched\"); } else if (title.equals(Send.title)) { } else if (title.equals(Update.title)) { } else if (title.equals(Info.title)) { } else if (title.equals(DelFriend.title)) { } else { try { } socket.close(); e.printStackTrace(); } catch (IOException e) { private void delFriendHandler() { } private void infoHandler() { String user = this.read(); this.read(); new FriendDAO().delete(user, this.currentUser); this.send(\"success\" + MessageEnd.end + DelFriend.title + MessageEnd.end + MessageEnd.end); } String username = this.read(); this.read(); User result = new UserDAO().getUserInfo(username); StringBuffer reply = new StringBuffer(); reply.append(\"success\" + MessageEnd.end + Info.title + MessageEnd.end); reply.append(result.getAge() + MessageEnd.end + result.getCity() + MessageEnd.end); + MessageEnd.end); + result.getUserName() + MessageEnd.end); reply.append(result.getGender() + MessageEnd.end + result.getNickName() reply.append(result.getPassWord() + MessageEnd.end reply.append(MessageEnd.end); this.send(reply.toString()); private void updateHandler() { } private void sendHandler(int id) { String target = this.read(); String content = this.read(); this.read(); if (Server.connections.containsKey(target)) { User user = new User(); user.setUserName(this.currentUser); user.setNickName(this.read()); user.setPassWord(this.read()); user.setCity(this.read()); user.setAge(Integer.parseInt(this.read())); user.setGender(this.read().charAt(0)); new UserDAO().update(user); this.send(\"success\" + MessageEnd.end + Update.title + MessageEnd.end + Messa geEnd.end); } } ServiceHandler hand = Server.connections.get(target); System.out.println(\"connection: \" + target + \"got\"); if (hand != null) { } System.out.println(\"connection: \" + target + \"got inside\"); hand.send(\"success\" + MessageEnd.end + \"send\" + MessageEnd.end + (id) + MessageEnd.end + this.currentUser + MessageEnd.end + content.replace('\\n', '#') + MessageEnd.end + MessageEnd.end); private void searchFriendHandler() { } private void registHandler() { User user = new User(); user.setUserName(this.read()); System.out.println(user.getUserName() + \" read\"); user.setPassWord(this.read()); String name = this.read(); String value = this.read(); this.read(); StringBuffer buffer = new StringBuffer(); buffer.append(\"success\" + MessageEnd.end); buffer.append(SearchFriend.title + MessageEnd.end); List buffer.append(MessageEnd.end); this.send(buffer.toString()); buffer.append(result.get(index) + MessageEnd.end); } System.out.println(user.getPassWord() + \" read\"); user.setNickName(this.read()); System.out.println(user.getNickName() + \" read\"); user.setCity(this.read()); System.out.println(user.getCity() + \" read\"); user.setGender(this.read().charAt(0)); user.setAge(Integer.parseInt(this.read())); this.read(); user.setOnline(false); if (new UserDAO().insertUser(user)) { } this.send(\"success\" + MessageEnd.end + Regist.title + MessageEnd.end + MessageEnd.end); } else { this.send(\"fail\" + MessageEnd.end + Regist.title + MessageEnd.end + MessageEnd.end); private void friendsHandler() { String request = this.read(); this.read(); List // this.send(\"success\" + MessageEnd.end+Friends.title + MessageEnd.end); Iterator System.out.println(\"send: \" + Arrays.toString(result.toArray())); private void loginHandle() { String userName = this.read(); String password = this.read(); System.out.println(userName); private void addFriendHandler() { } String f = this.read(); this.read(); Friend friend = new Friend(); friend.setFriendName(f); friend.setUserName(this.currentUser); new FriendDAO().inser(friend.getFriendName(), friend.getUserName()); this.send(\"success\" + MessageEnd.end + AddFriend.title + MessageEnd.end + MessageEnd.end); // this.send(AddFriend.title + MessageEnd.end + MessageEnd.end); } if (result.size() == 0) { } sendData.append(MessageEnd.end); this.send(sendData.toString()); // this.send(MessageEnd.end); System.out.println(\"list send over\"); sendData.append(\"NoFriend\" + MessageEnd.end); while (iterator.hasNext()) { } User user = iterator.next(); sendData.append(user.getUserName() + \" \" + (user.isOnline() ? \"在线\" : \"离线\") + MessageEnd.end); // this.send(user.getUserName() + \" \" // + (user.isOnline() ? \"在线\" : \"离线\") + MessageEnd.end); } } System.out.println(password); this.read(); if (new UserDAO().userLogin(userName, password)) { } else { } this.send(\"fail\" + MessageEnd.end + Login.title + MessageEnd.end + MessageEnd.end); Server.connections.put(userName, this); this.currentUser = userName; this.changeUserState(true); this.send(\"success\" + MessageEnd.end + Login.title + MessageEnd.end + MessageEnd.end); 4.软件测试 软件实现了基本的登录、注册、聊天、添加好友等功能,相关的测试也围绕着这些功能展开。 其中,在登录模块,进行测试的时候,输入各种情况的字符进行验证,看是否在程序中有漏洞。 在注册模块,验证用户名是否合法,验证用户两次输入的密码是否一致,验证用户输入的年龄是否是合法值。同时在注册模块,还需验证该用户名是否已经存在,避免重复申请等等。 在登录成功之后,要测试软件在功能上是否完全满足设计目标。 综合来看,该系统基本完成既定设计目标。 5.系统总结 以前很少接触到Java的图像化界面编程,运用起来显得有些生疏,做出来的系统界面上不是很美观,系统由于使用了Socket进程间通信以及多线程技术,在程序的并发控制上还有待改进。相较于C/S架构下的程序开发,我还是更倾向和擅长于B/S架构,毕竟,B/S架构下开发是未来开发的一个趋势。 6.参考文献 郑莉 王言行 马素霞 《Java语言程序设计》 北京:清华大学出版社 2005 陈冈, 陈智洁, 宋泽源 Java开发入行真功夫。北京: 电子出版社2009 李茏怡,Java编程实例讲解,高等教育出版社,2005.11 吴晓东 Java程序设计基础 清华大学出版社 2002-5-1 张孝祥 Java基础与案例开发详解 清华大学出版社 2009-9-1 鄢爱兰 Java参考大全 清华大学出版社 2005-11-1 王鹏、何昀峰 Java Swing图形界面开发与案例详解 清华大学出版社 2008-12-1 朱福喜、黄昊 Java项目开发与毕业设计指导 清华大学出版社 2008-6-1 因篇幅问题不能全部显示,请点此查看更多更全内容