a1411.docx
- 文档编号:28836731
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:16
- 大小:100.96KB
a1411.docx
《a1411.docx》由会员分享,可在线阅读,更多相关《a1411.docx(16页珍藏版)》请在冰豆网上搜索。
a1411
目录
1系统功能说明2
1.1系统简介2
1.2系统主要功能2
1.3系统开发环境3
2系统设计3
2.1系统总体设计3
2.2网络通信协议4
2.3数据存储4
2.4关键类设计6
3系统错误与调试10
3.1常见异常及处理方法10
3.2系统实现过程中遇到的错误及其解决方法10
4总结与体会13
4.1对于系统中采用的新技术的理解与思考13
4.2对于系统开发过程的总结与思考14
1系统功能说明
1.1系统简介
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,例如,国内的QQ、微信等等。
Java是一种程序设计语言,它具有简单的、完全面向对象以及与平台无关的结构,也具有可移植性、高性能和安全性,并提供了多线程的功能,而Java语言最大的成功之处在于它的平台无关性和具有强大的网络编程功能,基于Java网络编程的强大功能,本人将用Java编写一个在线网络聊天系统。
1.2系统主要功能
本次设计主要实现了以下几个功能:
●客户端功能设计如下:
(1)身份认证,该模块主要实现用户的登陆认证,以及检查数据的合法性。
(2)文字聊天功能,该模块主要用Socket实现不同用户之间消息的的发送,并且不仅仅传文本格式的数据,也可以传输图片,需要自己封装并自定义消息流,并能够识别显示。
(3)表情聊天功能,该模块主要实现了表情的使用。
(4)用户注册功能,该模块主要实现了用户的注册,包括详细资料的填写等等,然后通过socket把个人信息组成字符串发送给服务端进行解析。
●服务端功能设计如下:
(1)在线用户统计,该模块主要实现在线用户的查看显示,可以查看其详细资料。
(2)处理注册,该模块主要将用户注册的账号以及相关信息保存到文件中。
(3)发布信息,该模块主要服务器可以发布系统信息,使客户端可以接收。
1.3系统开发环境
(1)系统开发平台:
本系统采用eclipse及WINDOWS设计。
(2)硬件环境:
运行本系统的硬件基本要求如下:
CPU:
Inteli3及以上;
内存:
256MB及以上;
硬盘:
40GB及以上。
2系统设计
2.1系统总体设计
基于Java的网络聊天系统设计与实现主要考虑三个个方面的设计,即服务器模块设计,服务器客与客户端通信规则设计和客户端模块设计,本系统整体构架如图2.1所示。
图2.1系统整体构架图
2.2网络通信协议
系统采用的是TCP传输协议,主要实现服务器与客户端之间通信。
其具体思路是:
在服务器使用Socket通信的时候,把服务器与客户端通信的信息封装为一个String对象,然后通过自己手动将这些对象转化为输入流,并在另一端输出流,根据自己制定的规则逆序解析流,把流转化为对象,再解析字符串。
实现服务器与客户端之间的通信。
其中具体的表示信息要自己制定,比如登陆成功标示,失败标示,注册标示,聊天标示、系统提示等,这些都需要自己通过一些字符标记。
Socket程序的工作过程:
1、建立Socket连接:
在通信开始之前由通信双方确认身份,建立一条专用的虚拟连接通道。
2、数据通信:
利用虚拟连接通道传送数据信息进行通道。
3、关闭:
通信结束时,再将所建的虚拟连接拆除。
实现套接字的服务端,需要使用ServerSocket类。
ServerSocket类是服务器程序的运行基础,它允许程序绑定一个端口号来监听客户端的请求,一旦产生客户端请求,它将接受这一请求,同时产生一个完整的Socket连接对象。
服务器绑定的端口必须公开,以便让客户端程序知道如何连接这个服务器。
同时,作为服务器,它必须能够接收多个客户的请求,这就需要为服务器设置一个请求队列,如果服务器不能马上响应客户端的请求,要将这个请求放进请求队列中,等服务器将当前的请求处理完,会自动到请求队列中按照先后顺序取出请求进行处理。
服务器的资源是有限的,这就导致它的最大连接数是有限的,通过ServerSocket的构造函数可以指定这个最大连接数。
2.3数据存储
考虑到具体情况,本系统采用的是文件来进行数据的存储:
User.txt
主要用来存储用户名以及密码,主要用于登录身份验证。
Infor.txt
主要用来存储用户的详细信息,包括性别、地址、联系方式、签名、昵称等等。
Record.txt
主要用来存储聊天室的聊天记录,用于数据恢复。
文件读写的关键代码如下
写:
fout=newFileOutputStream("register.txt");//文件输出流
bout=newObjectOutputStream(fout);//对象输出流
info.name=str[1];//info为用户对象
info.pass=str[2];
bout.writeObject(info);//将信息对象写入文件中
bout.close();
fout.close();
System.out.println("name="+info.name+"\npass="+info.pass);
fin=newFileInputStream("register.txt");
bin=newObjectInputStream(fin);
info=(Infomation)bin.readObject();
RandomAccessFileraf=newRandomAccessFile(file,"rw");
if(file.exists()){
longlength=file.length();
raf.seek(length);
}
raf.writeUTF(info.name);
raf.writeUTF(info.pass);
raf.close();
bin.close();
fin.close();
读:
RandomAccessFileraf=newRandomAccessFile(file,"r");
Strings1=null;
Strings=null;
s1=raf.readUTF();
s1.trim();
2.4关键类设计
服务端:
(1).Chatserver.java
主要用于与客户端建立连接,New对应的服务线程。
publicclassChatserver{
staticfinalintport=6000;//端口
staticServerSocketserver;
staticVector
staticVector
staticintcount=0;
publicChatserver(){
}
publicstaticvoidmain(String[]args){
try{
server=newServerSocket(port);//启动服务端
System.out.println("聊天室服务端已启动...");
}catch(IOExceptione){
System.err.println(e);
System.exit
(1);
}
while(true){//死循环
try{
Socketsocket=server.accept();
ServerThreadcp=newServerThread(socket);//启动一个用户线程
Threadct=newThread(cp);
ct.start();
addConnection(socket,cp);//保存socket和服务线程
}catch(IOExceptione){
System.err.println(e);
System.exit
(1);
}
}
}
}
(2)ServerThread.Java
服务器模块核心功能是使用SocketServer实现多线程的服务器,针对每一个客户建立一个单独的线程处理客户端的请求。
其具体思路是,首先建立SocketServer,并绑定服务器IP和某个未使用的端口。
然后监听该端口,如果有客户端的Socket连接则建立一个客户端线程ServerThread类对象,有该对象处理该客户的一些请求,并在ServerThread中保存UserBean对象,该对象保存了用户的一些基本信息,比如账号、密码、年龄、是否在线等。
如果服务器没有关闭SocketServer则服务器则一直处理客户端连接。
其核心代码如下:
publicclassServerThreadimplementsRunnable{
publicServerThread(Socketsocket)throwsIOException{
this.s=socket;
in=newBufferedReader(newInputStreamReader(s.getInputStream()));
out=newPrintWriter(s.getOutputStream());
updateList();
}
publicvoidrun(){
while(true){
try{
Stringline=in.readLine();
Stringstr[]=line.split("&");
System.out.println("服务器收到消息:
"+line);
//解析字符串并进行对应操作
}
客户端:
(1).ChatClient.java
主要实现了图形界面,并且对服务端发送过来的消息进行解析,以下代码为解析消息部分,图形界面的实现就不列出。
publicclassChatClientextendsJFrameimplementsActionListener,Runnable,ListSelectionListener,ItemListener,KeyListener,MouseListener{
publicvoidrun(){
Stringinmsg;
while(true){
try{
if((inmsg=in.readLine())!
=null){
System.out.println("客户端接受到从服务器发来的消息为"+inmsg);
String[]key=inmsg.split("&");
if(key[0].equals("old")){
String[]userInfo=inmsg.split("&");
list.addElement(userInfo[1]);//更新用户列表
l1.setText("在线人数:
"+userInfo[3]);
}
elseif(key[0].equals("new"))//接收第一次服务器发送欢迎信息
{
String[]userInfo=inmsg.split("&");
list.addElement(userInfo[2]);//更新用户列表
tishi(tfp,"【系统消息】:
"+userInfo[2]+"上线了",Color.red);
l1.setText("在线人数:
"+userInfo[4]);
}elseif(inmsg.startsWith("quit")){
String[]s=inmsg.split("&");
inserts(tfp,"【系统消息】"+s[1]+s[2]);
l1.setText("在线人数:
"+s[3]);
out.println("FLUSH");
out.flush();
}elseif(inmsg!
=null)//一般消息
{
String[]sendfile=inmsg.split("&");
if(x=true){
String[]d=inmsg.trim().split(":
");
String[]s=inmsg.trim().split("&");
if(d.length>1&&s.length!
=2){
inserts(tfp,"【"+d[0]+"】:
"+d[1]);
}
}else{
String[]d=inmsg.trim().split(":
");
String[]s=inmsg.trim().split("&");
if(d.length>1&&s.length!
=2)
inserts(tfp,"【"+d[0]+"】"+":
"+d[1]);
}
}
}
}catch(Exceptionee){
ee.printStackTrace();
insert(tfp,"与服务器中断,请重新登录!
");
//将输出流,输入流设置为null
in=null;
out=null;
return;
}
}
}
3系统错误与调试
3.1常见异常及处理方法
(1).IOException
处理办法:
在进行文件操作后及时关闭i/o流,调用异常的对象的printStackTrace()方法,打印方法调用栈的异常信息,使用System.err.println进行输出。
(2).BadLocationException
处理办法:
计算文字以及图片具体的位置,捕获并给出提示。
doc=j.getStyledDocument();
doc.insertString(doc.getLength(),words+"\n",getFontAttrib().getAttrSet());
(3).NullPointerException
处理办法:
调用异常的对象的printStackTrace()方法,打印方法调用栈的异常信息,使用System.err.println进行输出。
3.2系统实现过程中遇到的错误及其解决方法
(1).图形界面的布局问题
错误:
界面各个组件的排布未达到预计要求
解决办法:
对整个界面采用Flowlayout、Bordlayout、Gridlayout嵌套布局
例如:
(以登录界面为例)
publicLogin(){
super("登录窗口");
p1=newJPanel();
p1.setBackground(newColor(055,155,255));
//左右图片
pf=newJPanel();
pr=newJPanel();
xp2=newJPanel();
xp3=newJPanel();
pc=newJPanel(newGridLayout(4,1));
p4=newJPanel();
p4.setBackground(newColor(055,155,255));
p4.add(enter);
p4.add(zhuce);
p3=newJPanel(newBorderLayout());
JPanelp=newJPanel(newBorderLayout());
p.add(p4,BorderLayout.SOUTH);//登录、注册
p.add(p3,BorderLayout.CENTER);
p.add(p1,BorderLayout.NORTH);//weicome
Containercon=getContentPane();
con.add(p);
}
(2).客户端与服务端发送消息问题
错误:
客户端与服务端发送消息时,发送后对方未能及时接受
解决办法:
out.flush();强制输出缓冲流
(3).文件I/O问题
错误:
文件读写之后未能及关闭导致数据错误
解决办法:
读写完毕后,及时关闭输入输出流,出于数据安全考虑
(4).客户端异常退出在线列表未能及时更新问题
错误:
客户端异常退出,未能更新在线列表
解决办法:
类似于心跳检测,服务器定时向所有客户端发送指定内容的消息,若没有收到回复则删除该客户端的Socket并结束该客户端对应的服务线程
/*增加连接,保存连接的socket*/
publicstaticvoidaddConnection(Sockets,ServerThreadcp){
if(connections==null){
connections=newVector
}
connections.addElement(s);
if(clients==null){
clients=newVector
}
clients.addElement(cp);//增加客户端的线程
}
/*客户端退出时,删除保存的相应socket和线程*/
publicstaticvoiddeleteConnection(Sockets,ServerThreadcp)throwsIOException{
if(connections!
=null){
connections.removeElement(s);
s.close();
}
if(clients!
=null){
clients.removeElement(cp);
}
}
/*获得客户端的线程*/
publicstaticVectorgetClients(){
returnclients;
}
4总结与体会
4.1对于系统中采用的新技术的理解与思考
(1).字符流
字符流I/O会自动将这个内部格式与本地字符集进行转换。
在西方的语言环境中,本地字符集通常是ASCII的8位超集。
对于大多数应用,字符流的I/O不会比字节流I/O操作复杂。
输入和输出流的类与本地字符集进行自动转换。
使用字符的程序来代替字节流可以自动适应本地字符集,并可以准备国际化,而这完全不需要程序员额外的工作。
(2).字节流
字节流处理原始的二进制数据I/O。
输入输出的是8位字节,相关的类为InputStream和OutputStream.字节流应只用于最原始的I/O。
所有其他流类型是建立在字节流之上的。
(3).文件I/O
Java中输入和输出组织不同于大多数其他语言。
它是建立在流(stream)上。
不同的基本流类(如java.io.FileInputStream)用于读写特定的数据资源。
但是所有的基本输出流使用同一种基本方法读数据。
(4).TCP
TransmissionControlProtocol传输控制协议,属于可靠性传输,适合不容许有传输错误的网络程序设计使用。
TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。
相比之下UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。
Socket是程序与网络间的一种接口,大部分网络应用程序都是点对点的,所谓点就是服务器端和客户端所执行的程序。
Socket是用来接收和传送分组的一个端点。
(5).Swing
本系统采用JavaSwing实现图形界面,在实际开发中,javaswing用的并不多主要是因为有许多先进的开源技术来设计界面,但对于小型系统来说,使用javaswing来设计界面还是一个不错的选择。
(6).对象流
在本系统中,将每一个注册用户封装为一个info对象,因此在注册、登录校验模块都通过对象流来进行文件操作,ObjectOutput/InputStream这套对象的序列化、反序列化机制的优化,在对象可能重复的情况下,能有效减低IO开销。
例如:
ObjectInputStreambin=null;
ObjectOutputStreambout=null;
Infomationinfo=newInfomation("","","","","","");
fout=newFileOutputStream("userr.txt");//文件输出流
bout=newObjectOutputStream(fout);//对象输出流
info.name=str[1];
info.pass=str[2];
bout.writeObject(info);//将信息对象写入文件中
bout.close();
fout.close();
4.2对于系统开发过程的总结与思考
(1).在进行开发之前,应该确定使用的技术,例如TCP或者UDP并且明确具体的消息发送逻辑。
比如客户端与客户端之间的通讯是否通过服务器、服务器如何向全部客户端发送消息等等。
(2).一个好的界面往往能为一个产品带来加分,因此在开发之前应该对整体界面有一个简单的设计并在后期根据实际情况进行优化。
(3).团队协作是开发过程中必不可少的一部分,相互之间的及时沟通、交流能够减少很多不必要的工作。
(4).对文件I/O、字符流、字节流、对象流、Javaswing、TCP、UDP等技术的掌握是开发的基础。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- a1411