聊天室系统设计报告文档格式.docx
- 文档编号:21510005
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:34
- 大小:583.12KB
聊天室系统设计报告文档格式.docx
《聊天室系统设计报告文档格式.docx》由会员分享,可在线阅读,更多相关《聊天室系统设计报告文档格式.docx(34页珍藏版)》请在冰豆网上搜索。
将数据源和目的封装成数据包中,不需要建立连接;
每个数据报的大小在限制在64k;
因无连接,是不可靠协议;
不需要建立连接,速度快。
TCP:
建立连接,形成传输数据的通道;
在连接中进行大数据量传输;
通过三次握手完成连接,是可靠协议;
必须建立连接,效率会稍低。
2.3Socket
(1)Socket套接字
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
(2)Socket原理机制
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
2.4TCP传输
(1)客户端思路
A建立客户端的Socket服务,并明确要连接的服务器。
B如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
C通过Socket对象的方法,可以获取这两个流
D通过流的对象可以对数据进行传输
E如果传输数据完毕,关闭资源
(2)服务器端思路
A建立服务器端的socket服务,需要一个端口
B服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
C通过客户端的获取流对象的方法,读取数据或者写入数据
D如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的
2.5Java的多线程机制
进程:
每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。
线程:
同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
多进程是指操作系统能同时运行多个任务(程序),多线程是指在同一程序中有多个顺序流在执行。
在java中,每次程序运行至少启动2个线程。
一个是main线程,一个是垃圾收集线程。
因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,启动JVM实际上就是在操作系统中启动了一个进程。
在java中所有的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
三、需求分析
实现聊天的功能,采用Java
Socket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,可将所有信息发往服务器端,再由服务器进行处理,服务器端是所有信息的中心。
3.1客户端
3.1.1登录
用户需要填写用户名、服务器地址、端口号才可以进入聊天室与在线用户聊天,此外,服务器地址默认是本机地址,端口号默认是5000。
用户名可以中文,英文字母或标点符号,服务器地址必须是符合点分十进制的合法地址,端口号可以修改,但服务器端程序内默认端口号也必须修改。
该聊天室不需要注册,直接登录即可聊天,退出后,系统不保留用户任何信息。
若新登录用户与在线用户的用户名重名,则系统会自动修改用户名。
格式为:
用户名+“_客户端线程ID”。
3.1.2多人聊天
每个在线用户都可以发送聊天信息,服务器端会一直监听,并把每一个在线用户发送的聊天信息转发到每一个客户端。
聊天室的聊天信息格式为:
用户名时间(yyyy-MM-ddHH:
mm:
ss)
聊天信息
3.1.3单人聊天
用户可以选择某一个在线用户实现单人聊天,该聊天信息不会在聊天室显示,只有单聊的两个人能够看到。
单人聊天的聊天信息格式为:
mm)
3.2服务器端
服务器端主要处理客户端的请求,包括用户的登录,发送多人聊天信息,退出聊天室,单人聊天请求,发送单人聊天信息,并且随时更新在线用户列表。
四、总体设计
4.1设计思想流程图
4.2设计思想分析
首先启动服务器,它会建立一个专门用于接收客户端连接请求的“倾听Socket”,然后等待客户的连接请求。
当用户登录输入信息后,与服务器建立Socket连接,服务器端的“倾听Socket”收到连接请求后,会接受连接请求,并生成一个服务器端socket,专门负责与此客户端socket的通信。
一旦连接请求成功,客户端将信息及请求通过本方socket的输出流发送给服务器端相应的socket,服务端则通过服务器端Socket的输入流接受客户端传输过来的信息及请求,分析是何请求,然后根据请求类型,进行相应的处理(如登录、私聊等)。
服务器端也可以根据需要,通过socket的输出流发送信息和请求给客户端。
客户端和服务器端都可以通过关闭本方的socket而结束一次通信过程。
对于客户端的各种请求,实际上都是通过在客户端发往服务器的各种字符流区分的,具体的方法就是在消息的内部添加特殊字符串,从而实现服务器对消息请求的识别。
比如对于登陆信息,消息中添加的内容就是“@login”,而对于私聊中的消息,消息中添加的内容就是“@single”,其他的同理都添加了相应内容。
当然,对于客户端来说,这些都是透明的,用户的操作并没有受到任何影响。
在服务器端,消息被检测分析后,变回根据具体的目的进行处理,比如是私聊消息,服务器便会根据其内部添加的信息,向目标端转发该条消息,当目标端接收到连接请求后,会主动建立一个私聊窗口,从而实现私聊。
服务器端需要能同时接受多个用户的请求,为了实现这一点,一般使用多线程机制来处理,对每一个客户端连接通信,服务器端都有一个线程专门负责处理。
对于客户端的各种请求,内部添加的信息分别如下:
●@clientThread客户端线程启动
messages.add(clientThread.getId()+"
@clientThread"
);
客户端线程ID
●@login登录客户端
username+"
@login"
+getThreadID()+"
用户名+客户端线程ID
●@userlist用户列表
serverThread.users.get(newInteger(threadID))+"
@userlist"
+threadID+"
用户名+客户端线程ID
●@chat群聊
username+"
@chat"
+getThreadID()+"
+mess+"
用户名+客户端线程ID+聊天信息
●@serverexit服务器退出
serverThread.messages+"
@serverexit"
●@single单聊
client.username+"
@single"
+client.getThreadID()+"
+(int)client.clientuserid.get(index)+"
+mess+"
;
用户名+客户端线程ID+客户端线程ID+聊天信息
●@exit退出群聊
@exit"
五、详细设计
5.1客户端设计
5.1.1登录界面
5.1.2聊天室界面
5.1.3单人聊天界面
5.2服务器端设计
六、系统测试
6.1登录测试
6.1.1用户名为英文字母
6.1.2用户名为中文
6.1.3用户名为标点符号
6.1.4多个用户有重名
6.1.5服务器地址不合法
6.1.6端口号不合法
6.1.7服务器未开启
6.2群发消息测试
6.3私聊测试
6.4用户列表显示测试
无论已经登录用户的退出,还是新用户成功登录,用户列表显示部分都能正确显示。
七、心得体会
这段时间通过不断的修改,我终于把聊天室系统完成了,虽然它只有简单的聊天功能,但通过它,我不但巩固了以前学的知识,而且学到了许多在课堂中学不到的知识。
通过这次课程设计,我更坚定了理论与实际相结合是十分重要的想法,即使一个人读了再多的技术图书,但没有相关的实践经验,那么他也不会真正地掌握一门技术。
只有把理论知识与实践相结合,才会深入的了解并提高自己的独立思考能力。
通过这次的课程设计,我将自己所学的Java语言得到了实际的应用,在完成的过程中也遇到了许多困难,但通过不断地查阅资料,最终还是解决了,在这个过程中,我学会了独立思考,同时也让我明白完成一件事情要不断开阔视野,拓展知识面,解放自己的思维。
总之,在完成课程设计的过程中,我学会了如何克服开发中遇到的技术困难,学会了独立面对并解决问题。
八、参考资料
叶核亚JAVA程序设计实用教程(第2版)电子工业出版社
朱福喜,路迟JAVA语言与面向对象程序设计武汉大学出版社
沈文炎Java高级编程机械工业出版社
九、程序清单
(1)Client.java
publicclassClientextendsThread{
publicSocketc_socket;
//套接字
privateClient_chatFramec_chatFrame;
//聊天室聊天界面
privateClient_enterFramec_enterFrame;
//客户端登录界面
privateClient_singleFramec_singleFrame;
//单人聊天界面
publicDataInputStreamdis=null;
//IO输入
publicDataOutputStreamdos=null;
//IO输出
privatebooleanflag_exit=false;
//客户端未启动标记
privateintthreadID;
//聊天室客户端线程标记
publicMap<
String,Client_singleFrame>
c_singleFrames;
//单人聊天,用户名为键,单聊客户端为值
publicList<
String>
username_online;
//在线用户
Integer>
clientuserid;
//用户ID
publicStringusername=null;
//用户名
publicStringchat_re;
//通道内相关信息
//getter,setter方法
publicClient_chatFramegetC_chatFrame(){
returnc_chatFrame;
}
publicClient_singleFramegetC_singlFrame(){
returnc_singleFrame;
publicvoidsetC_singlFrame(Client_singleFramec_singlFrame){
this.c_singleFrame=c_singlFrame;
publicvoidsetC_chatFrame(Client_chatFramec_chatFrame){
this.c_chatFrame=c_chatFrame;
publicClient_enterFramegetC_enterFrame(){
returnc_enterFrame;
publicvoidsetC_enterFrame(Client_enterFramec_enterFrame){
this.c_enterFrame=c_enterFrame;
publicintgetThreadID(){
returnthreadID;
publicvoidsetThreadID(intthreadID){
this.threadID=threadID;
//客户端构造函数
publicClient(){
c_singleFrames=newHashMap<
();
username_online=newArrayList<
clientuserid=newArrayList<
//signlechatuse=newArrayList<
//main方法,设置进入时登录界面
publicstaticvoidmain(String[]args){
Clientclient=newClient();
Client_enterFramec_enterFrame=newClient_enterFrame(client);
client.setC_enterFrame(c_enterFrame);
c_enterFrame.setVisible(true);
//登录客户端
publicStringlogin(Stringusername,StringhostIp,StringhostPort){
this.username=username;
Stringlogin_mess=null;
//错误信息或true
try{
c_socket=newSocket(hostIp,Integer.parseInt(hostPort));
}catch(NumberFormatExceptione){
login_mess="
连接的服务器端口号port为整数,取值范围为:
1024<
port<
65535"
returnlogin_mess;
}catch(UnknownHostExceptione){
主机地址错误"
}catch(IOExceptione){
连接服务器失败,请稍后再试"
}
return"
true"
//创建一个客户端聊天界面,启动一个线程
publicvoidshowChatFrame(Stringusername){
getDataInit();
c_chatFrame=newClient_chatFrame(this,username);
c_chatFrame.setVisible(true);
flag_exit=true;
//客户端已启动
this.start();
//启动线程
//初始化,建立连接通道
privatevoidgetDataInit(){
dis=newDataInputStream(c_socket.getInputStream());
dos=newDataOutputStream(c_socket.getOutputStream());
e.printStackTrace();
//该类声明为Thread的子类,重写Thread类的run方法
publicvoidrun(){
while(flag_exit){//客户端已启动
try{
//readUTF():
读入一个已使用UTF-8修改版格式编码的字符串。
chat_re=dis.readUTF();
}catch(IOExceptione){
flag_exit=false;
if(!
chat_re.contains("
)){
chat_re=null;
}
}
if(chat_re!
=null){
if(chat_re.contains("
intlocal=chat_re.indexOf("
setThreadID(Integer.parseInt(chat_re.substring(0,local)));
//启动客户端线程,设置ThreadID
try{
dos.writeUTF(username+"
}catch(IOExceptione){
e.printStackTrace();
}
}else{
if(chat_re.contains("
c_chatFrame.setDisUsers(chat_re);
}else{
if(chat_re.contains("
c_chatFrame.setDisMess(chat_re);
}else{
if(chat_re.contains("
c_chatFrame.closeClient();
}else{
if(chat_re.contains("
c_chatFrame.setSingleFrame(chat_re);
}
}
}
//发送聊天信息
publicvoidtransMess(Stringmess){
dos.writeUTF(username+"
//聊天室中退出聊天
publicvoidexitChat(){
flag_exit=false;
System.exit(0);
//登录之前退出
publicvoidexitLogin(){
System.exit(0);
//服务器关闭,退出聊天室客户端,在Client_chatFrame中调用
publicvoidexitClient(){
flag_exit=false;
}
(2)WinCenter.java
publicclassWinCenter{
publicstaticvoidcenter(Windowwin){
Toolkittkit=Toolkit.getDefaultToolkit();
//使用系统工具包
DimensionsSize=tkit.getScreenSize();
//屏幕尺寸
DimensionwSize=win.getSize();
//窗体尺寸
if(wSize.height>
sSize.height){
wSize.height=sSize.height;
if(wSize.width>
sSize.width){
wSize.width=sSize.width;
win.setLocation((sSize.width-wSize.width)/2,(sSize.height-wSize.height)/2);
//窗体居屏幕中央
(3)Server.java
publicclassServer{
privateServerFrameserverFrame;
privateServerThreadserverThread;
publicServerFramegetServerFrame(){
returnserverFrame;
publicvoidsetServerFrame(ServerFrameserverFrame){
this.serverFrame=serverFrame;
publicServer(){}
//启动服务器线程
publicvoidstartServer(){
try{
serverThread=newServerThread(serverFrame);
}catch(Exceptione){
serverThread.setFlag_exit(true);
serverThread.start();
//停止服务器线程
publicvoidstopServer(){
synchronized(serverThread.messages){//同步代码块:
synchronize
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 聊天室 系统 设计 报告