软件工程课程设计Socket聊天系统Word下载.docx
《软件工程课程设计Socket聊天系统Word下载.docx》由会员分享,可在线阅读,更多相关《软件工程课程设计Socket聊天系统Word下载.docx(31页珍藏版)》请在冰豆网上搜索。
![软件工程课程设计Socket聊天系统Word下载.docx](https://file1.bdocx.com/fileroot1/2022-12/27/3fd62bab-a05f-4c34-aafd-ce16755356cb/3fd62bab-a05f-4c34-aafd-ce16755356cb1.gif)
在登陆的情况下选择你要聊天的好友,进行信息的传送,实现彼此的聊天,这也是本系统最基本的功能。
2.1.2群聊(一对多):
可以实现一对多人的聊天。
2.1.3大文件传输:
在能够聊天的基础上,实现通讯的多元化,进行文件的传输。
是通讯双方可以选择传送对方想获得的资料。
2.1.4点歌
2.1.5分组管理
2.1.6个人信息管理
2.1.7用户管理
2.1.8视频通话
2.2非功能需求:
2.2.1界面友好:
界面易操作性,对经典的聊天程序的界面进行了学习和借鉴,模仿他们的界面和常用的操作。
2.2.2网络安全
加密
解密
为了提高传输的安全性,进行加密操作。
及时在网络上被别人了窃听消息,也不能得到原始信息,防止个人重要信息和隐私信息被盗。
2.3用例分析
2.3.1参与者
本系统显而易见的两个参与者:
用户和管理员。
2.3.2用例分析
从上面的需求里进行抽象和提取关键信息,在确定系统边界的情况下,选择最基本的用例,然后对用例进行描述和细化。
使其能完全的描述系统的功能性需求。
2.3.3系统的用例图
通过对参与者和用例的分析,确定他们的关系(包括参与者和参与者的关系,参与者和用例的关系,用例之间的关系。
)其中用例之间的关系是分析中的重点,如图私聊和群聊都有socket聊天的模块,所以可以确定的是包含关系。
管理个人信息,包含了分组管理和用户信息管理,其中分组管理和用户信息管理,是个人信息管理的子集,所以应该是泛化关系。
在文件传输的时候,可能会产生信息的丢失,导致信息不完整,接收方不能完整收到发送方的消息,所以导致发送方重发信息。
所以这是扩展关系,因为只有在传输文件失败的时候,才能启用重传文件的模块。
用户所参与的模块首先应该登录,在登录系统后,可以私聊和群聊来交流信息。
用户可以管理自己的信息进行修改自己的信息和管理自己的分组。
为了丰富系统的功能我,我们还特意实现了点歌功,和传输文件吸引用户的眼光。
3.总体设计
3.1TCP服务器设置
在T
C
P
/
I
P协议族中,有两个互不相同的传输协议:
T
P(传输控制协议)和U
D
P(用户数据报协议)。
P为两台主机提供高可靠性的数据通信。
它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。
由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。
而另一方面,
U
P则为应用层提供一种非常简单的服务。
它只是把称作数据报的分组从一台主机发到另一台主机,但并不保证该数据报能到达另一端。
任何必需的可靠性必须由应用层来提供。
3.2分析类图
(系统整齐的分析类图)
没有类是单独存在的,通常和别的类协作,创造比单独工作更大的语义。
因此,除了捕获系统的词汇以外,还要将注意力集中到这些类是如何在一起工作的。
使用类图来表达这种协作。
确定你建模的机制。
机制代表了部分你建模的系统的一些功能和行为,这些功能和行为是一组类、接口和其他事物相互作用的结果。
对于每个机制,确定类、接口和其他的参与这个协作的协作。
同时确定这些事物之间的关系。
用场景来预排这些事物,沿着这条路你将发现模型中忽略的部分和定义错误的部分。
确定用这些事物的内容来填充它们。
对于类,开始于获得一个责任(类的职责),然后,将它转化为具体的属性和方法。
3.3顺序图
3.2.1用户私聊顺序图
用户在进入系统前首先要输入彼此通讯的端口号,由于客户机和服务器都是本机所以不需要寻找IP地址,然后输入用户名新建一个用户,由于没有保存历史记录功能,所以每次进入系统前都需要新建一个用户。
然后输入用户名和密码,在确认用户和密码。
登陆成功,选择在线可以聊天的好友,输入信息然后发送,达到和好友的交流。
3.2.2用户传送文件序列图
3.3协作图
3.3.1用户私聊协作图
强调的是发送和接收消息的对象之间的组织结构。
一个协作图显示了一系列的对象和在这些对象之间的联系以及对象间发送和接收的消息。
对象通常是命名或匿名的类的实例,也可以代表其他事物的实例。
3.3.2用户传送文件协作图
用户在登录系统后,进入登陆界面,在界面的好友框里,选择要传送文件的好友,点击传送文件的按钮,会弹出选择文件的对话框,在对话框里查找你所在的文件系统中你要传送的文件。
然后点击传送。
4.详细设计
4.1客户端设计
一个网络聊天室的运行,首先是要有一个完整稳定的服务器端,并且拥有很多个服务器端。
客服端要具有实现用户注册和用户登陆,在登陆成功后,要显示出公聊界面,实现聊天功能并且能够发送表情和保存聊天内容和显示聊天记录等功能,在新用户上线和用户下线时要更新每个客户端在线用户列表名,并且可以和在线的用户实现一对一的私聊功能。
在服务器端可以实现不断的监听客服的连接,并且根据客户端发送过来的不同信息如注册信息,登录信息,公聊信息,私聊信息,退出信息等,服务器端要做出不同的响应,并且要实现数据库的操作,如根据用户注册的信息保存数据库中,根据登录时发送来的用户名和密码检测是否合法用户等。
经为每一个连接着的客户端建立了一个线程,这个线程好比一根电话线一直等待客户端说话,而信息发送中心就相当于一个总台,一旦有人打电话进来,就通过电话线把信息传
完成了服务器端的第一个的任务,那么第二个任务也就不难解决了。
上面已送到总台,再由总台根据需要将这个信息发送给接收群。
这样
就意味着,服务器每接受一条信息,就要调用一次信息发送中心的方法,并将这条信息发送到所有客户端(或者特定的某个/某几个客户端)。
电脑每做的一次动作,一个步骤,都是按照以经用计算机语言编好的程序来执行的,程序是计算机要执行的指令的集合,而程序全部都是用我们所掌握的语言来编写的。
所以人们要控制计算机一定要通过计算机语言向计算机发出命令。
侦听服务器发送的连接请求,有请求就接收发来的信息,并通过短信猫发出去
单的说,服务器端是为客户端服务的,服务的内容诸如向客户端提供资源,保存客户端数据等等.客户端可以是任意的一台电脑,只要它和服务器端存在连接,并且得到了服务器端的授权,就可以使用服务器端的服务.象现在就可以理解为XX的网站是服务器端,我们现在使用的电脑就是客户端.我们可以使用它的服务.
4.2服务端设计
由于客户端需要同时能够接收信息以及发送信息,所以也必须利用多个线程来实现。
主线程用于接收用户输入的内容并将之发送到服务器端,而一个后台线程将一直接收来自服务器端的信息,并将之返回给客户端的用户。
客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。
除了一些只在本地运行的应用程序之外,一般安装在普通的客户机上,需要与服务端互相配合运行。
因特网发展以后,较常用的用户端包括了如万维网使用的网页浏览器,收寄电子邮件时的电子邮件客户端,以及即时通讯的客户端软件等。
对于这一类应用程序,需要网络中有相应的服务器和服务程序来提供相应的服务,如数据库服务,电子邮件服务等等,这样在客户机和服务器端,需要建立特定的通信连接,来保证应用程序的正常运行。
不过客户端及伺服端的关系不见得一定建立在两台分开的机器上,同一台机器中也有这种主从关系的存在。
提供服务的伺服端及接受服务的客户端也有可能都在同一台机器上,例如我们在提供网页的服务器上执行浏览器浏览本机所提供的网页,这样在同一台机器上就同时扮演伺服端及客户端。
4.3多线程设计
为了能实现一对多的通话聊天也就是说间接的多对多的聊天的功能,所以必须在客户端配置和服务端配置的时候。
实现多线程的功能。
实现程序的并发。
以及可以减少创建进程是CPU的资源浪费。
和服务区负荷太重。
多线程在客户端可以实现,用户进行群聊,以及接受多个好友的响应信息。
在服务端可以减少创建进程的开销。
在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。
多线程处理一个常见的例子就是用户界面。
利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。
使用线程可以把占据时间长的程序中的任务放到后台去处理用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
程序的运行速度可能加快,在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。
在这种情况下可以释放一些珍贵的资源如内存占用等等。
但是如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换。
更多的线程需要更多的内存空间。
线程可能会给程序带来更多“bug”,因此要小心使用。
线程的中止需要考虑其对程序运行的影响。
通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生。
5.代码实现
5.1服务端设计
publicclassServerFrameextendsJFrame{
privateJPanelcontentPane;
privateJTextFieldtxtPort;
privateJLabellblState;
privateJTextAreatxtAllUsers;
//集合:
用来保存所有登录的用户
privateList<
UserInfo>
allLoginUser=null;
publicstaticvoidmain(String[]args){
EventQueue.invokeLater(newRunnable(){
publicvoidrun(){
try{
ServerFrameframe=newServerFrame();
//禁止用户更改窗体的大小
frame.setResizable(false);
//距中
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}catch(Exceptione){
e.printStackTrace();
}
}
});
}
publicServerFrame(){
allLoginUser=newArrayList<
();
initComponet();
publicList<
getAllLoginUser(){
returnallLoginUser;
publicvoidsetAllLoginUser(List<
allLoginUser){
this.allLoginUser=allLoginUser;
privatevoidinitComponet(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100,100,449,506);
contentPane=newJPanel();
contentPane.setBorder(newEmptyBorder(5,5,5,5));
setContentPane(contentPane);
contentPane.setLayout(null);
JPanelpanel=newJPanel();
panel.setBorder(newTitledBorder(UIManager
.getBorder("
TitledBorder.border"
),
"
\u670D\u52A1\u5668\u4FE1\u606F"
TitledBorder.LEADING,
TitledBorder.TOP,null,newColor(0,70,213)));
panel.setBounds(10,10,421,143);
contentPane.add(panel);
panel.setLayout(null);
JLabellabel=newJLabel("
\u670D\u52A1\u5668\u72B6\u6001\uFF1A"
);
label.setBounds(48,38,81,23);
panel.add(label);
lblState=newJLabel("
Newlabel"
lblState.setBounds(161,42,110,15);
panel.add(lblState);
JLabellabel_1=newJLabel("
\u670D\u52A1\u5668\u7AEF\u53E3\uFF1A"
label_1.setBounds(48,87,81,15);
panel.add(label_1);
txtPort=newJTextField();
txtPort.setBounds(161,84,110,21);
panel.add(txtPort);
txtPort.setColumns(10);
JButtonbtnStart=newJButton("
\u542F\u52A8\u670D\u52A1\u5668"
btnStart.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
startServer(e);
}catch(IOExceptione1){
//TODOAuto-generatedcatchblock
e1.printStackTrace();
btnStart.setBounds(289,83,93,23);
panel.add(btnStart);
JPanelpanel_1=newJPanel();
panel_1.setBorder(newTitledBorder(null,
\u5DF2\u7ECF\u767B\u5F55\u7684\u7528\u6237"
TitledBorder.LEADING,TitledBorder.TOP,null,null));
panel_1.setBounds(20,163,411,299);
contentPane.add(panel_1);
panel_1.setLayout(newBorderLayout(0,0));
txtAllUsers=newJTextArea();
panel_1.add(txtAllUsers,BorderLayout.CENTER);
publicvoidupdateGui(){
this.txtAllUsers.setText(null);
for(inti=0;
i<
this.allLoginUser.size();
i++){
this.txtAllUsers.append(allLoginUser.get(i).getUserName());
this.txtAllUsers.append("
\n"
}
protectedvoidstartServer(ActionEvente)throwsIOException{
//验证:
是否为空的验证
if(CommValidate.isEmpty(txtPort.getText())){
JOptionPane.showMessageDialog(null,"
端口号不能空"
return;
//端口必须是数字
if(!
CommValidate.isDigit(txtPort.getText())){
端口号必须是数字"
//1024之上
//建立一个监听socket
intport=Integer.parseInt(txtPort.getText());
ServerSocketserverSocket=newServerSocket(port);
ServerListerenThreadserverListeren=newServerListerenThread(
serverSocket,this);
this.lblState.setOpaque(true);
this.lblState.setForeground(Color.red);
this.txtPort.setEnabled(false);
//禁用
}
5.2客户端设计
publicclassClientLoginextendsJFrame{
privateJTextFieldtxtLoginUser;
privateJTextFieldtxtAddress;
privateSocketsocket;
//登录用户信息
privateUserInfologinUser=null;
publicUserInfogetLoginUser(){
returnloginUser;
publicvoidsetLoginUser(UserInfologinUser){
this.loginUser=loginUser;
publicSocketgetSocket(){
returnsocket;
publicvoidsetSocket(Socketsocket){
this.socket=socket;
privateServerSocketserverSocket;
ClientLoginframe=newClientLogin();
frame.setAlwaysOnTop(true);
publicClientLogin(){
setBounds(100,100,397,298);
panel.setBorder(newTitledBorder(null,"
\u7528\u6237\u767B\u5F55"
panel.setBounds(10,10,369,244);
\u7528\u6237\u540D\uFF1A"
label.setBounds(37,36,54,15);
txtLoginUser=newJTextField