基于UDP协议网上聊天程序 课程设计.docx
《基于UDP协议网上聊天程序 课程设计.docx》由会员分享,可在线阅读,更多相关《基于UDP协议网上聊天程序 课程设计.docx(24页珍藏版)》请在冰豆网上搜索。
基于UDP协议网上聊天程序课程设计
基于UDP协议网上聊天程序课程设计
湖南工业大学
课程设计
资料袋
计算机与通信学院学院(系、部)2013~2014学年第1学期
课程名称网络协议分析指导教师李建设职称副教授
学生姓名专业班级网络工程学号
题目基于UDP协议网上聊天程序
成绩起止日期2013年11月25日~2013年12月13日
目录清单
序号
材料名称
资料数量
备注
1
课程设计任务书
2
课程设计说明书
3
4
5
6
课程设计任务书
2013—2014学年第1学期
学院(系、部)计算机与通信学院专业网络工程班级102
课程名称:
网络工程学生姓名:
设计题目:
基于UDP协议网上聊天程序指导教师:
李建设
完成期限:
自2013年11月25日至2013年12月13日共3周
内
容
及
任
务
一、设计内容
实现一个基于UDP协议的简单的聊天程序,包括服务器和客户端。
1.支持多人聊天。
2.客户端具有图形化用户界面。
二、设计任务
课程设计说明书(纸质+电子版),内容包括:
设计内容、系统分析(包括可行性分析、需求分析等)及功能分析;系统设计(要求画出系统整体功能框图、流程图、并给出相应地关键的代码且对所使用的主要数据结构进行说明等。
)、设计总结(评价/遇到的问题/体会/建议等)、使用说明等。
三、设计要求
1.按功能要求开发系统,能正确运行。
程序代码书写规范,有充足的注释。
2.课程设计所使用的编程语言任选,但建议使用C或C++;
3.绿色软件:
程序运行不需安装,避免写系统和注册表;
进
度
安
排
起止日期
工作内容
2013-11-25~2013-11-30
选题
2013-12-1~2013-12-3
系统分析和设计;
2013-12-4~2013-12-8
熟悉软件开发工具、编码系统、系统测试
2013-12-9~2013-12-13
撰写并提交课程设计说明书(含电子文档)、源程序等。
主
要
参
考
资
料
[1](美)W.RechardSteven著,范建华等译,《TCP/IP详解》卷1:
协议,机械工业出版社,2000.4
[2](美)DouglasE.Comer著,林瑶等译,《用TCP/IP进行网际互联》第1卷-原理、协议与结构(第5版,电子工业出版社)2007.2;
[3](荷)AndrewS.Tanenbaum著,潘爱民译.《计算机网络》(第4版),清华大学出版社,2004
[4]谢希仁著.《计算机网络》((第5版),电子工业出版社,2008.1
[5]吴功宜等著.《计算机网络课程设计》,机械工业出版社,2005
指导教师(签字):
年月日
系(教研室)主任(签字):
年月日
课程设计说明书
课程名称:
网络协议分析
设计题目:
基于UDP协议网上聊天程序
专业:
班级:
学生姓名:
学号:
指导教师:
李建设
2013年12月13日
1课程设计简介4
1.1课程设计的目的4
1.2课程设计内容4
2课程设计实现过程5
2.1协议原理5
2.2客户机/服务器模式7
2.3关键技术8
2.4流程图10
2.5系统结构图11
2.6程序调试及界面效果图11
2.7源代码15
3设计总结22
4参考文献23
1课程设计简介
1.1课程设计的目的
开发一个专用于实现两台计算机之间即时通讯的软件,以方便两台或两台以上的计算机之间信息的交流。
,在连接并通信时,尤其是近程的即时通讯,彻底的脱离了远程的服务器,避免了和远程服务器连接时过多的浪费网络资源。
并且避免了服务器忙或与服务器无法连接时,浪费过多时间用于和服务器建立连接!
因此,这个软件是极具适应性和实用性的即时通讯软件!
本次课程设计的目的是学习基于UDP协议实现网络聊天程序,已达到学会面向无连接方式的程序设计方法,并理解网络编程中面向无连接的概念。
1.2课程设计内容
1.实现一个基于UDP协议的简单的聊天程序,包括服务器和客户端。
2.支持多人聊天。
3.客户端具有图形化用户界面。
2课程设计实现过程
2.1协议原理
UDP协议的全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。
在OSI模型中,在第四层——传输层,处于IP协议的上一层。
UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
UDP用来支持那些需要在计算机之间传输数据的网络应用。
包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。
UDP协议基本上是IP协议与上层协议的接口。
UDP协议适用端口分别运行在同一台设备上的多个应用程序。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
UDP协议的主要作用是将网络数据流量压缩成数据包的形式。
一个典型的数据包就是一个二进制数据的传输单位。
每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
UDP是无连接的,即发送数据之前不需要建立连接(当然发送数据结束时也没有连接可释放)因此减少了开销和发送数据之前的时延。
UDP使用的是尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。
UDP是面向报文的。
发送方的UDP对应程序交下来的报文,在添加首部后就向下交付给IP层。
UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。
UDP是定义用来在互连网络环境中提供数据报交换的计算机通信的协议。
此协议默认是IP下层协议。
此协议提供了向另一用户程序发送信息的最简便的协议机制,不需要连接确认和保护复制,所以在软件实现上比较简单,需要的内存空间比起TCP相对较小。
UDP包头由4个域组成,其中每个域各占用2个字节。
(1)源端口号(16位):
UDP数据包的发送方使用的端口号。
(2)目标端口号(16位):
UDP数据包的接收方使用的端口号。
UDP协议使用端口号为不同的应用保留其各自的数据传输通道。
UDP和rap协议正是采用这一机制,实现对同一时刻内多项应用同时发送和接收数据的支持。
(3)数据报长度(16位)。
数据报的长度是指包括报头和数据部分在内的总的字节数。
理论上,包含报头在内的数据包的最大长度为65535字节。
不过,一些实际应用往往会限制数据包的大小,有时会降低到8192字节。
(4)校验值(16位)。
UDP协议使用包头中的校验值来保证数据的安全。
××××××
(正文字体要求为宋体,字号为小四,行间距20磅,每段前空2字符)
2.2客户机/服务器模式
由于这次课程设计是实现点到点的可靠连接,所以在此使用UDP连接方式。
在这个连接中,双方分为客户和服务器,他们各自的功能不同。
客户机一方,UDP应用程序功能如下:
(1)打开通信信道(申请一套接字),并连接到服务器在主机的保留端口,该端口对应服务器的UDP进程。
(2)向服务器发出请求报文,等待接收应答。
(3)从服务器方收到最终应答结果,或在不再请求时关闭信道并终止客户机进程。
服务器一方,UDP应用程序动作如下:
(1)打开通信信道(申请一套接字),通知本地主机在某一保留端口接收客户机请求。
(2)等待客户请求到达指定端口。
(3)接收到请求,启动一新进程处理用户请求,同时释放旧进程以响应新的客户请求,一旦服务完成,关闭新进程与客户的通信链路。
(4)继续等待客户机请求。
(5)如果不想响应客户机请求,关闭服务器进程。
2.3关键技术
Socket又称作套接字,它是使用 标准Unix 文件描述符 (file descriptor) 和其它程序通讯的方式。
使用send()和recv()让你更好的控制数据传输。
在Java网络编程中,socket相当于应用程序的港口码头;在计算机网络中,套接字由ip地址和端口号组成,为进程之间通信提供地址。
两个主机进行通信实际上就是两个主机中的应用进程互相通信,应用进程之间的通信又称为端到端的通信。
为应用进程之间的通信提供运输服务的是运输层的运输协议,运输层需要有两种不同的运输协议,即面向连接的TCP和无连接的UDP。
在Java中,用于实现基于UDP的聊天程序,使用两个重要的类(DatagramSocket类和DatagramPacket类)。
DatagramSocket类表示用来发送和接收数据报包的套接字。
数据报套接字是包投递服务的发送或接收点。
每个在数据报套接字上发送或接收的包都是单独编址和路由的。
从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
在DatagramSocket上总是启用UDP广播发送。
为了接收广播包,应该将DatagramSocket绑定到通配符地址。
在某些实现中,将DatagramSocket绑定到一个更加具体的地址时广播包也可以被接收。
DatagramPacket类表示数据报包。
数据报包用来实现无连接包投递服务。
每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。
从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
不对包投递做出保证。
服务程序工作在服务器的某个端口上,一旦启动服务,它将在这个端口上监听,等待客户程序发来请求,当有客户连接到该端口,accept()方法就返回一个Socket对象,可以用该对象获得一个输入输出流。
服务器的套接字用服务器套接字类(ServerSocket)来建立。
具体实现如下:
(1)建立一个服务者,端口为6666。
(2)服务者永远等待,一旦客户送来正确的请求,连接至该端口,accept()方法就返回一个Socket对象。
(3)用返回的Socket对象创建数据输入流类的实例6666。
用返回的Socket对象创建数据输出流的实例8888。
以上实例in和out是服务者用于从客户接受输入信息和向客户程序发送信息所用。
此外,还需要用方法receive()和printIn()读取或输出一行数据。
(4)在客户端建立Socket对象,并进行异常处理,主机名和端口号与连接的服务器名和提供该服务的服务程序的监听端口必须一致。
建立连接后用Socket类提供的Datagramsocket()和Datagrampacket()方法取得输入输出流。
在服务器端,获得的输入流是客户端的输出流,而Socket获得的输出流是发向客户端的输入流,在客户端也是这样。
获得socket的输入输出流之后,为了便于读写操作,需要在这两个流对象基础上建立易于操作的数据流Datagramsocket,Datagrampacket。
然后对输入输出流进行读写操作。
在通信结束时关闭socket,以断开连接,释放资源。
先关闭对应的输入输出流,再关闭socket本身。
2.4流程图
服务器端
Socket建立流式套接字,返回套接字
waitforpackets检测并接受对方发来的消息
waitforpackets检测并接受对方发来的消息
Socket建立流式套接字,返回套接字
Bind将套接字号宇本地地址相连
waitforpackets接收来自客户的数据
处理请求
Button1_actionPerformed发送信息给对方
Button1_actionPerformed发送信息给对方
Close关闭
数据请求
数据应答
客户端
2.5系统结构图
Server服务器(192.168.1.77)
ChatApp_01客户端(192.168.1.68)
ChatApp_02客户端(192.168.1.78)
ChatApp_03客户端(192.168.1.88)
2.6程序调试及界面效果图
2.6.1调试前的准备
安装jdk1.6.0并在计算机的环境变量中配置好java环境。
使用的实验环境是WindowsXP,Eclipse6.0,。
使用3太主机进行通信,一台作为服务器,另外两台作为客户端。
2.6.2程序调试过程
启动eclipse首先在一台主机上运行服务器端程序,再在另外两台机器上运行客户端程序。
然后进入到用户的图形用户界面,输入客户端的IP,进行连接,如果连接成功,则客户端就可以通过与服务器端进行通信,然后服务器转发通信,实现了两个客户端之间的聊天功能。
2.6.3程序运行结果
服务器(192.168.1.77)
ChatApp_01客户端(192.168.1.68)
ChatApp_02客户端(192.168.1.78)
ChatApp_03客户端(192.168.1.88)
2.7源代码
ChatFram.java
packageChatFrame_01;
import.*;
importjava.io.*;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
importjava.lang.*;
importjava.awt.color.*;
importjavax.swing.JOptionPane;
publicclassChatFrameextendsJFrame{
JPanelcontentPane;
JLabellabel1=newJLabel();//发送消息
JLabellabel2=newJLabel();//输入ip
Labellabel3=newLabel();//输入端口标签
Labellabel4=newLabel();//输出端口标签
JTextFieldtextField1=newJTextField();//发送消息
JTextFieldtextField2=newJTextField();//输入ip
JTextFieldtextField3=newJTextField();//获得输入端口
JTextFieldtextField4=newJTextField();//获得输出端口
JButtonbutton1=newJButton("发送");//发送消息
TextAreatextArea1=newTextArea();
JOptionPanejopane=newJOptionPane();
DatagramPacketsendpacket,receivepacket;//声明发送和接收数据包
DatagramSocketsendsocket,receivesocket;//声明发送和接收DatagramSocket
publicChatFrame(){
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try{
toInit();
}catch(Exceptione){
e.printStackTrace();
}
}
privatevoidtoInit()throwsException{
contentPane=(JPanel)this.getContentPane();
label1.setText("发送信息:
");
label1.setBounds(newRectangle(13,100,60,21));
contentPane.setLayout(null);
contentPane.setBackground(Color.pink);
this.setSize(newDimension(363,502));
this.setTitle("多人聊天室");
label2.setText("输入对方IP地址:
");
label2.setBounds(newRectangle(12,19,109,23));
label3.setText("输入端口:
");
label3.setBounds(newRectangle(12,58,55,22));
label4.setText("输出端口:
");
label4.setBounds(newRectangle(180,58,55,22));
textField3.setText("3000");
textField4.setText("3001");
button1.setBounds(newRectangle(280,100,59,21));
button1.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(ActionEvente){
button1_actionPerformed(e);
}
});
textField1.addKeyListener(newKeyAdapter(){
publicvoidkeyPressed(KeyEvente){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
Stringstr=textField2.getText();
Stringstr1=textField1.getText();
if(pareTo("")!
=0&&!
"".equals(str1)){
try{
textArea1.append("\nto"+textField2.getText()
+":
"+"3000"+"say:
"
+textField1.getText());
Strings=textField1.getText();
bytedata[]=s.getBytes("UTF-8");
sendpacket=newDatagramPacket(
data,
data.length,
InetAddress.getByName("192.168.1.77"),
6666);
sendsocket.send(sendpacket);
}catch(IOExceptionexc){
exc.printStackTrace();
}
textField1.setText("");
}
}
}
});
textField4.setBounds(newRectangle(240,58,90,22));
textField3.setBounds(newRectangle(70,58,90,22));
textField2.setBounds(newRectangle(123,20,120,19));
textField1.setBounds(newRectangle(76,100,190,19));
textArea1.setBounds(newRectangle(11,140,333,315));
textArea1.setEditable(false);
textArea1.setBackground(Color.white);
contentPane.add(label4,null);
contentPane.add(label3,null);
contentPane.add(label2,null);
contentPane.add(label1,null);
contentPane.add(textField1,null);
contentPane.add(textField2,null);
contentPane.add(textField3,null);
contentPane.add(textField4,null);
contentPane.add(textArea1,null);
contentPane.add(button1,null);
this.setVisible(true);
bind();
}
protectedvoidprocessWindowEvent(WindowEvente){
super.processWindowEvent(e);
if(e.getID()==WindowEvent.WINDOW_CLOSING){
System.exit(0);
}
}
publicvoidwaitforpackets(){//检测并接受对方发来的消息
while(true){
try{
byte[]array=newbyte[100];
receivepacket=newDatagramPacket(array,array.length);
receivesocket.receive(receivepacket);//接收
textArea1.append("\nfrom"+receivepacket.getAddress()+":
"
+receivepacket.getPort()+"get:
");
Stringreceived=newString(receivepacket.getData(),0,
receivepacket.getLength(),"