课题名称: 即时通讯系统设计(淮信QQ)姓名:
班级:
学号:
即时通讯系统设计(淮信QQ)
一、人员组成及组员分工
1、人员组成
张圣筛,赵华祥,李军,朱稼霖
2、组员分工
(1)框架的构建:赵华祥
此模块包括CientMain ServerMain 的编写及其启动流程
ClientProcessor ServerProcessor 处理器线程的编写及其流程
以及包括服务器窗体的编写
(2)登录、注册、注册信息的编写:朱稼霖
包括LoginFrame RegistFrame RegistInfoFrame 的编写及其服务器的响应
登录时服务器的处理包括检测用户合法性、登记在线用户、将好友发给登录用户以及通知好友上线等流程
(3)SinChatRoom 的编写:李军
包括发送聊天消息的流程服务器接受聊天消息并转发的流程对方客户端的接受流程包括客户端发送服务器接受客户端接受
该模块还包括窗口抖动要求发送端和接收端窗体都要抖动一共4个流程
(4)ListFrame的编写:张圣筛
成员列表窗口的编写。包括渲染器的改写,上线、下线的编写及其流程,在服务器端可捕获下线异常。
二、分组模块详细设计
3、模块功能概述:
我负责的是第一模块,框架的构建,此模块包括CientMain ServerMain 的编写及其启动流程,ClientProcessor ServerProcessor 处理器线程的编写及其流程,以及包括服务器窗体的编写
(1)ServerMain:设置外观感觉,读取配置文件,连接到数据库,并显示服务器窗体
(2)ServerManage:服务器窗体,通过窗体界面,对服务器端进行操作,和反馈相关信息
(3)ServerProcessor:服务器处理器线程,接受客户端和服务器端的请求,并进行处理与
反馈
(4)CientMain:初始化套接字I/O流,初始化登录界面并显示
(5)ClientProcessor:客户端处理器线程,连接到服务器,并显示客户端窗体
4、系统设计流程图:
(1)ServerMain:
Java课程设计
(2)ServerManage:
2
即时通讯系统设计(淮信QQ)(3)CientMain:
5、运行效果及关键代码
(1)Server
ServerMain:
try{
//配置文件读取
Java课程设计
SAXReader saxReader = new SAXReader();
Document docXML = saxReader.read("config.data");
Element root = docXML.getRootElement();
Element serverInfo = root.element("server-info");
Element serverIP = serverInfo.element("ip");
Element serverPort = serverInfo.element("port");
ServerData.setPORT(Integer.parseInt(serverPort.getText()));
}catch(Exception e){
JOptionPane.showMessageDialog(null, "配置文件读取异常", "错误信息", JOptionPane.ERROR_MESSAGE);
}
ServerData.serverFrame=new ServerManager();
ServerData.serverFrame.setVisible(true);
ServerManager:
if(ServerData.serverSocket==null){
try{
ServerData.serverSocket=new ServerSocket(ServerData.PORT);
}catch(Exception e){
e.printStackTrace();
}
this.getjTextInfo().append("服务器启动,监听端口"+ServerData.PORT+"\n");
}
new Thread(new Runnable(){
public void run(){
while(true){
try{
Socket s=ServerData.serverSocket.accept();//阻塞,监听,后服务器线程
new Thread(new ServerProcessor(s)).start();//启动线程
}catch(Exception e){
e.printStackTrace();
}
}
}
}).start();
this.jButton1.setEnabled(false);
ServerProcessor:
int uid;//用户的数据库ID号
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
User user = null;
4
即时通讯系统设计(淮信QQ)
V ector
V ector
String rand = null;
ImageIcon imageIcon = null;
rand = ServerUtil.randString();
imageIcon = ServerUtil.getCheckImageIcon(rand);
System.out.println("随机数"+rand);
try{
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
TCPResponse checkImageResponse = new TCPResponse();
checkImageResponse.setrType(ResponseType.CHECKIMAGE);
checkImageResponse.getAttributeMap().put("image", imageIcon);
oos.writeObject(checkImageResponse);
TCPRequest tcpRequest = null;
while((tcpRequest = (TCPRequest)ois.readObject()) != null)
{
RequestType requestType = tcpRequest.getrType();
switch(requestType)
{
case ASKFORCHECKIMAGE:{
}break;
case LOGIN:{
String name=(String)tcpRequest.getAttribute("username");
String pass=(String)tcpRequest.getAttribute("userpass");
System.out.println(name+" "+pass);
V ector
*from QQUser where uID='"+name+"'AND uPass='"+pass+"'");
if(vv.size()>0){
user =User.getUser(name);
ServerData.serverFrame.getjTextInfo().append("用户"+name+"上线("+")("+socket.getInetAddress().getHostAddress()+")\n");
user.setStatus(1);
//注册在线用户
ServerData.SOCKETS.put(user, socket);
ServerData.OOSMAP.put(user, oos);
ServerData.OISMAP.put(user, ois);
int
id=Integer.parseInt(vv.elementAt(0).elementAt(0).toString());
uid=id;
//获取用户好友,并初始化frinendUser
friendUser=ServerUtil.getFreind(uid,user);
System.out.println(friendUser);
Java课程设计
TCPResponse response=new TCPResponse();
response.setrType(ResponseType.LOGINOK);
response.setAttribute("frienduser", friendUser);
oos.writeObject(response);
oos.flush();
ServerUtil.tellOnline(friendUser,user);//通知好友其上线了
}else{
System.out.println("非法用户");
}
}break;
case REGIST:{//客户端注册信息
User registuser=(User)tcpRequest.getAttribute("ruser");
String pass=(String)tcpRequest.getAttribute("password");
System.out.println(registuser+pass);
registuser.setPass(pass);
System.out.println(registuser+pass);
ServerUtil.registUser(registuser);
if(ServerUtil.registUser(registuser)>0){
System.out.println("用户注册成功"+registuser);
TCPResponse response=new TCPResponse();
response.setrType(ResponseType.REGISTOK);
response.setAttribute("user", registuser);
response.setAttribute("pass", registuser);
try{
oos.writeObject(response);
oos.flush();
}catch(Exception e){
e.printStackTrace();
}
}
}break;
case SINTEXT:{
User touser=(User) tcpRequest.getAttribute("touser");
String message=(String) tcpRequest.getAttribute("message");
TCPResponse response=new TCPResponse();
response.setrType(ResponseType.SINTEXT);
response.setAttribute("fromuser",user);
response.setAttribute("message",message);
try{
if(ServerData.OOSMAP.get(touser)!=null)
ServerData.OOSMAP.get(touser).writeObject(response);
}catch(Exception e){
6
即时通讯系统设计(淮信QQ)
e.printStackTrace();
}
}break;
case MULTEXT:{
}break;
case SHAKEFRAME:{
User sf= (User)tcpRequest.getAttribute("shakefriend");
if(ServerData.OOSMAP.get(sf)!=null){
TCPResponse response=new TCPResponse();
response.setrType(ResponseType.SHAKEFRAME);
response.setAttribute("friend", user);
ServerData.OOSMAP.get(sf).writeObject(response);
ServerData.OOSMAP.get(sf).flush();
}
(2)Client:
public class ClientMain
{
public static void main(String[] args)
{
ClientLookFeel.setLoginLookFeel();
try{
//根据IP和POR T初始化套接字
System.out.println("其次运行初始化套接字I/O流");
ClientData.clientSeocket = new
Java课程设计
Socket(ClientData.ip,Integer.parseInt(ClientData.port));
ClientData.oos = new ObjectOutputStream(ClientData.clientSeocket.getOutputStream());
ClientData.ois = new ObjectInputStream(ClientData.clientSeocket.getInputStream());
}catch(Exception e){
e.printStackTrace();
System.out.println("服务器连接失败!");
ClientData.clientSeocket = null;
ClientData.oos = null;
ClientData.ois = null;
}
System.out.println("开始初始化登录界面并显示");
if(ClientData.clientSeocket != null && ClientData.oos!=null && ClientData.ois!=null){ Thread t = new Thread(new ClientProcessor());
ClientData.tMain = t;
t.start();
}
System.out.println("客户端启动...");
ClientData.loginFrame=new LoginFrame();
ClientData.loginFrame.setVisible(true);
}
}
ClientProcessor:
try{
TCPResponse tcpResponse = null;
while((tcpResponse = (TCPResponse)ois.readObject()) != null)
{
switch(tcpResponse.getrType())
{
case LOGINOK:{
V ector
System.out.println("客户端接收信息"+friend);
/* 对公共字段的好友向量设置*/
ClientData.friend=friend;
//先初始化公共字段中的列表模型和渲染器
ClientData.ulm=new UserListModel();
ClientData.ulr=new UserListRender();
if(ClientData.listFrame==null){
ClientData.listFrame=new ListFrame();
ClientData.listFrame.setV isible(true);
8
即时通讯系统设计(淮信QQ)
ClientData.loginFrame.dispose();
}
}break;
case LOGINFAIL:{
}break;
case REGISTOK:{
User u=(User)tcpResponse.getAttribute("user");
User pass=(User)tcpResponse.getAttribute("pass");
ClientData.registFrame.dispose();
if(ClientData.registInfoFrame==null){
ClientData.registInfoFrame=new RegistInfoFrame();
}
ClientData.registInfoFrame.getjLabelInfo().setText("注册成功,请记住你的ID号");
ClientData.registInfoFrame.getjTextArea1().append("QQ号:"+u.getId()+"\n");
ClientData.registInfoFrame.getjTextArea1().append("密码:"+pass.getuPass()+".");
ClientData.registInfoFrame.setVisible(true);
}break;
case REGISTFAIL:{
}break;
case SINTEXT:{
String message=(String)tcpResponse.getAttribute("message");
User fuser=(User)tcpResponse.getAttribute("fromuser");
if(ClientData.sinFrameMap.get(fuser)==null){
SinChatRoom sRoom=new SinChatRoom(fuser);
ClientData.sinFrameMap.put(fuser, sRoom);
}
ClientData.sinFrameMap.get(fuser).getjTextReceive().append(message);
ClientData.sinFrameMap.get(fuser).setV isible(true);
ClientData.sinFrameMap.get(fuser).toFront();//将窗口弹至最上
}break;
case MULTEXT:{
}break;
case CHECKIMAGE:{
}break;
/**验证码错误*/
case CHECKWRONG:{
Java课程设计
}break;
case FRIENDONLINE:{
User friend=(User)tcpResponse.getAttribute("friend");//获取上线好友
int indx=ClientData.friend.indexOf(friend);//获取该上线好友向量中的序列号
ClientData.friend.elementAt(ClientData.friend.indexOf(friend)).setStatus(1);//修改好友状态在线
UserListModel.regroupUsers();//重新排序好友
ClientData.ulm.fireAllData();//通知数据源以改变,重新绘制列表
}break;
case FRIENDOFFLINE:{
User friend=(User)tcpResponse.getAttribute("friend");//获取下线好友
int indx=ClientData.friend.indexOf(friend);//获取该上线好友向量中的序列号
ClientData.friend.elementAt(ClientData.friend.indexOf(friend)).setStatus(0);//修改好友状态离线
UserListModel.regroupUsers();//重新排序好友
ClientData.ulm.fireAllData();//通知数据源以改变,重新绘制列表
}break;
catch(Exception e){
e.printStackTrace();
JOptionPane.showMessageDialog(null, "与服务器连接已中断", "账号异常信息", https://www.wendangku.net/doc/472342743.html,RMA TION_MESSAGE);
System.exit(0);
三、总结
为期两个礼拜的JAVA实训结束了,从本次实训中学习到了很多平时上课不能学习到的东西,从原来什么都不懂,到现在已经懂了很多。实训的内容是模仿我们很熟悉的QQ软件,做一个及时聊天的工具,听起来就感觉难度很大。刚开始的几天就悲剧了,都是听老师在讲天书,意思都不懂,后来渐渐的对老师所讲的内容有所了解。
前一周是都在为QQ软件的实现做铺垫,老师让我们对QQ软件的实现有了基本的了解。后一周进入了主题——实现淮信QQ的功能,开始都是看着老师的发的视频,抄写代码,基本是不懂代码含义,也有惰性不想去了解,后来在跟其他组员的学习讨论中,慢慢对代码有了初步的了解。而后在接下来的实训时间中有了进一步的加强。感觉在准备实训的过程中,是学到最多,一大堆的问题都过来找你,多亏了向同学请教,不然真的什么都不会。
两周的实训说短也不短说长也不长,总来的来说还是能学到一些东西,虽然前期都不会,但是在后来却是了解到了很多。
10