




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
《计算机网络》课程设计说明书题目:基于UDP协议网上聊天程序学院:计算机科学与工程学院专业:信息平安姓名:学号:1000360222指导教师:孙晋永目录1协议介绍和使用说明31.1协议内容31.2关键技术41.2.1效劳器端Socket的实现41.2.2通信的建立52程序设计62.1系统结构62.2主程序设计72.2.1效劳器端程序72.2.2客户端程序72.3各模块设计8客户端向效劳器发送消息8客户端之间发送消息82.4界面设计82.4.1聊天界面设计的方法82.4.2界面的功能92.5实现主要代码92.6程序调试及运行结果152.6.1调试前的准备152.6.2程序调试过程162.6.3程序运行结果163课设体会17参考文献181协议介绍和使用说明1.1协议内容本课程设计主要是基于UDP的并用Java实现的简单的聊天程序。UDP用户数据报是在运输层的端到端抽象的逻辑信道中传送的。UDP在传送数据之前不需要先建立连接。对方的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP是一种最有效的工作方式。虽然UDP用户数据报只能提供不可靠的交付,但UDP在某些方面有其特殊的优点,它有即时通信的功能。比方说,使用聊天程序聊天的时候,省去的了跟对方通信的时候的链接的麻烦,直接进行通信。UDP只在IP的数据报效劳之上增加了很少一点的功能,即端口的功能和过失检测的功能。UDP使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制。UDP是面向报文的。UDP没有拥塞控制,很适合多媒体通信的要求。UDP支持一对一、一对多、多对一和多对多的交互通信。发送方UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保存这些报文的边界。应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。接收方UDP对IP层交上来的UDP用户数据报,在去除首部后就原封不动地交付上层的应用进程,一次交付一个完整的报文。图1.1UDP根本工作过程1.2关键技术效劳器端Socket的实现Socket又称作套接字,它是使用标准Unix
文件描述符(file
descriptor)
和其它程序通讯的方式。使用send()和recv()让你更好的控制数据传输。在Java网络编程中,socket相当于应用程序的港口码头;在计算机网络中,套接字由ip地址和端口号组成,为进程之间通信提供地址。两个主机进行通信实际上就是两个主机中的应用进程互相通信,应用进程之间的通信又称为端到端的通信。为应用进程之间的通信提供运输效劳的是运输层的运输协议,运输层需要有两种不同的运输协议,即面向连接的TCP和无连接的UDP。在Java中,用于实现基于UDP的聊天程序,使用两个重要的类〔DatagramSocket类和DatagramPacket类〕。DatagramSocket类表示用来发送和接收数据报包的套接字。数据报套接字是包投递效劳的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。在DatagramSocket上总是启用UDP播送发送。为了接收播送包,应该将DatagramSocket绑定到通配符地址。在某些实现中,将DatagramSocket绑定到一个更加具体的地址时播送包也可以被接收。atagramPacket类表示数据报包。数据报包用来实现无连接包投递效劳。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。效劳程序工作在效劳器的某个端口上,一旦启动效劳,它将在这个端口上监听,等待客户程序发来请求,当有客户连接到该端口,accept〔〕方法就返回一个Socket对象,可以用该对象获得一个输入输出流。效劳器的套接字用效劳器套接字类〔ServerSocket〕来建立。具体实现如下:(1)建立一个效劳者,端口为5000。(2)效劳者永远等待,一旦客户送来正确的请求,连接至该端口,accept〔〕方法就返回一个Socket对象。(3)用返回的Socket对象创立数据输入流类的实例in。用返回的Socket对象创立数据输出流的实例out。以上实例in和out是效劳者用于从客户接受输入信息和向客户程序发送信息所用。此外,还需要用方法readline〔〕和println〔〕读取或输出一行数据。(4)soc.close〔〕关闭Socket。图1.2基于UDP的SOCKET编程模型通信的建立在客户端建立Socket对象,并进行异常处理,主机名和端口号与连接的效劳器名和提供该效劳的效劳程序的监听端口必须一致。建立连接后用Socket类提供的getInputStream〔〕和getOutputStream〔〕方法取得输入输出流。在效劳器端,获得的输入流是客户端的输出流,而Socket获得的输出流是发向客户端的输入流,在客户端也是这样。获得socket的输入输出流之后,为了便于读写操作,需要在这两个流对象根底上建立易于操作的数据流DateInputStream,DataOutputStream。然后对输入输出流进行读写操作。在通信结束时关闭socket,以断开连接,释放资源。先关闭对应的输入输出流,再关闭socket本身。2程序设计2.1系统结构本系统采用一个效劳器端和多个客户端的聊天方式来实现。结构图如下所示:图2.1效劳器-客户端结构图2.2主程序设计效劳器端程序效劳器与客户间通过套接口Socket连接。在java中使用套接口相当简单,JavaAPI为处理套接口的通信提供了一个类.Socket.,使得编写网络应用程序相对容易.效劳器采用多线程以满足多用户的请求,程序用vector向量数组存储连接客户变量,通过创立一个ServerSocket对象来监听来自客户的连接请求,默认端口为6666,然后无限循环调用accept()方法接受客户程序的连接。客户端程序客户端是一个JavaApplet程序,客户通过Socket建立与效劳器的连接。图2.2主程序流程图2.3各模块设计客户端向效劳器发送消息效劳器与客户都通过构造DataInputStream,PrintStream来建立输入输出流,然后双方通过该输入输出流来相互传递信息,一旦收到客户方的连接请求,效劳器accept()方法返回一个新建的Socket对象。客户端然后向效劳器发送消息,客户端之间发送消息客户间发送信息通过UDP协议来实现,用户登录时通过类DatagramPacket和DatagramSocket创立UDP包括其本地接受端口以及发送端口,默认端口为newDatagramSocket〔〕和nickNameField.getText〔〕,通过向效劳器发送消息,然后效劳器播送消息,最好到达群聊的目的。客户端发送消息〔send(DatagramPacket)和接受消息(receive(DatagramPacket))。2.4界面设计2.4.1聊天界面设计的方法在Frame布局容器中,添加一个显示聊天的TextArea文本框〔在上面〕,参加Panel面板,Panel面板中包括一个发送消息的TextField单行文本框,“聊天记录〞和“发送〞两个按钮监听。图2.3聊天界面实现功能图2.4.2界面的功能①客户端登陆界面输入效劳器IP,接收端口,及用户名。登陆效劳器,与效劳器建立连接,进入聊天界面。②客户端聊天界面,进行聊天。并可查看聊天记录。③效劳器界面,监听客户端连接状况并可发送效劳器消息。2.5实现主要代码客户端代码:packageudp;importjava.io.*;importjava.awt.*;importjava.awt.event.*;import.*;classClientimplementsActionListener,Runnable{privateFrameframe,f1,f2;//聊天窗口和登陆窗口privatePanelp1,p2,p3;privateButtonsendButton,b,c,d;privateTextFieldserverIpField,sendField,receivePortField,nickNameField;privateTextAreacurrentUserField;booleanisClient=false;privateTextAreamessageArea;//聊天记录框privateStringserverIp;privateintserverReceivePort=6666;//效劳器接收默认端口privateDatagramSocketreceiveSocket=null,sendSocket=null;privateDatagramPacketreceivePacket=null,sendPacket=null;//客户端登陆界面publicvoidinputIP(){ }//聊天记录界面publicvoidinput(){ }//客户端聊天界面publicvoidlaunchFrame(){ }//启动客户端,完成登录publicvoidstart(){try{sendSocket=newDatagramSocket();//客户机发送端口 sendMessage(nickNameField.getText()+":" +receivePortField.getText()+":");//名字和接收端口newThread(this).start(); }catch(Exceptione){messageArea.append(e+"\n"); } }//客户端发送消息publicvoidsendMessage(Stringstr){try{ ByteArrayOutputStreamout=newByteArrayOutputStream();//捕获内存缓冲区的数据,转换成字节数组 PrintStreampout=newPrintStream(out);//输出字节 pout.print(str);byte[]buf=out.toByteArray();sendPacket=newDatagramPacket(buf,buf.length,InetAddress .getByName(serverIp),serverReceivePort);//构造数据报包sendSocket.send(sendPacket);//发送数据报包 buf=null; }catch(Exceptione){ e.printStackTrace();messageArea.append("消息:"+str+"发送失败,你还没有登录,或已经掉线!\n"); } }//多线程,启动接收信息publicvoidrun(){ receiveMessage(); }//客户机接收消息publicvoidreceiveMessage() {try{receiveSocket=newDatagramSocket(Integer .parseInt(receivePortField.getText()));//客户机接受端口while(true){byte[]buf=newbyte[200];receivePacket=newDatagramPacket(buf,buf.length);receiveSocket.receive(receivePacket);if(receivePacket.getLength()==0){messageArea.append("空消息"+"\n");continue; } ByteArrayInputStreambin=newByteArrayInputStream(receivePacket.getData());//字节串变成输入流 BufferedReaderread=newBufferedReader(newInputStreamReader( bin));//先把字节流转换为字符流,然后放入缓冲区 Stringstr=read.readLine();messageArea.append(str);if(str.contains("迎:/")){ }messageArea.append("\n"); read.close(); bin.close(); } }catch(Exceptione){messageArea.append(e+"sendmessageerror\n");} }//事件响应处理publicvoidactionPerformed(ActionEvente){ }//程序主入口publicstaticvoidmain(String[]args){ Clientclient=newClient();//client.input(); client.inputIP(); }效劳端端代码:packageudp;importjava.io.*;importjava.awt.*;importjava.awt.event.*;import.*;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;importjava.util.Iterator;publicclassServerimplementsActionListener{privateFrameframe;//主窗体privateLabelconnectLabel,messageLabel;privateTextAreamessageArea;//消息框,显示用户登录信息privateTextFieldsendField;//输入聊天内容的文本框privateButtonsendButton;//发送按钮privateDatagramSocketreceiveSocket=null,sendSocket=null;privateDatagramPacketreceivePacket=null,sendPacket=null;privateintserverReceivePort=6666;//效劳器端的接收端口privateList<ClientMessage>clientList=newArrayList<ClientMessage>();//保存连接的客户端信息booleanisServer=true;//程序主入口publicstaticvoidmain(String[]args){ Serverserver=newServer(); server.launchFrame(); server.start();//启动效劳器 server.receiveMessage();//接收信息 }//效劳端界面初始化publicvoidlaunchFrame(){ }//事件监听处理publicvoidactionPerformed(ActionEvente){ } }//启动效劳器publicvoidstart(){try{sendSocket=newDatagramSocket(6660);//效劳器发送端口 }catch(Exceptione){messageArea.append(e+"\n"); } }//效劳器接收消息publicvoidreceiveMessage() {try{receiveSocket=newDatagramSocket(serverReceivePort);//效劳器接受端口while(true){byte[]buf=newbyte[200];receivePacket=newDatagramPacket(buf,buf.length);receiveSocket.receive(receivePacket);intlength=clientList.size();booleanhave=false; ByteArrayInputStreambin=newByteArrayInputStream(receivePacket.getData()); BufferedReaderread=newBufferedReader(newInputStreamReader( bin)); Stringstr=read.readLine();for(inti=0;i<length;i++){ ClientMessageoldMsg=clientList.get(i);if(oldMsg.hasClient(receivePacket.getPort(),receivePacket.getAddress())){ have=true;break; } }//未存在此客户端if(!have){ ClientMessagenewMsg=newClientMessage( Integer.parseInt(str.split(":")[1].trim()),receivePacket.getPort(),receivePacket.getAddress());messageArea.append("用户:"+str.split(":")[0] +"进入聊天室,其IP地址:" +receivePacket.getAddress().getHostAddress() +"发送端口:"+newMsg.getSendPort()+"接收端口:" +newMsg.getReceivePort()+"登录时间:" +newDate()+"\n");clientList.add(newMsg); sendMessage("热烈欢送:"+str.split(":")[0]+"IP:" +receivePacket.getAddress().getHostAddress() +"参加聊天室!\n"); }else{//用户已经存在 sendMessage(str); } read.close(); bin.close(); } }catch(Exceptione){///e.printStackTrace();messageArea.append(e+"sendmessageerror\n"); } }//效劳器端发送消息给客户端publicvoidsendToClient(){ }//效劳器播送消息publicvoidsendMessage(Stringstr){ ByteArrayOutputStreamout=newByteArrayOutputStream(); PrintStreampout=newPrintStream(out); pout.print(str);byte[]buf=out.toByteArray();//缓冲区intlength=clientList.size();try{//转发给每一个在线用户for(inti=0;i<length;i++){ ClientMessagemsg=clientList.get(i);sendPacket=newDatagramPacket(buf,buf.length, msg.getClientIp(),msg.getReceivePort());sendSocket.send(sendPacket); } }catch(IOExceptione){ e.printStackTrace(); } buf=null; }}classClientMessage{privateintreceivePort;//客户端的接收端口privateintsendPort;//客户端的发送端口privateInetAddressclientIp;//客户端的IPpublicClientMessage(intreceivePort,intsendPort,InetAddressclientIp){this.receivePort=receivePort;this.clientIp=clientIp;this.sendPort=sendPort; }publicintgetReceivePort(){returnreceivePort; }publicInetAddressgetClientIp(){returnclientIp; }publicintgetSendPort(){returnsendPort; }publicbooleanhasClient(intsendPort,InetAddressip){if(ip.getHostAddress().equals(this.getClientIp().getHostAddress()) &&sendPort==this.getSendPort()){returntrue; }returnfalse; }}2.6程序调试及运行结果2.6.1调试前的准备安装jdk并在计算机的环境变量中配置好java环境。使用的实验环境是Windows7,EclipseSDK版本:,。2.6.2程序调试过程启动eclipse,单机测试。首先在主机上运行效劳器端程序,再在器上运行3个客户端程序。然后进入到用户的图形用户界面,输入效劳器的IP,进行连接,如果连接成功,那么客户端就可以通过与效劳器端进行通信,然后效劳器转发通信,实现了多个客户之间的聊天
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2025学年高中数学 第3章 数系的扩充与复数的引入 3.2 复数代数形式的四则运算 3.2.2 复数代数形式的乘除运算(教师用书)教学实录 新人教A版选修2-2
- 郑州信息科技职业学院单招职业技能测试参考试题(附答案)
- DB14T 3224-2024艺术档案收集与整 理规范
- 小学教科研活动总结
- 电气自动化专业实习报告
- 广告业务年度总结
- 房东房屋租赁合同
- 网络公司网站建设合同
- 五星级酒店改造工程装修合同
- 2025年哈尔滨货运资格证模拟考试
- 2024年苏州市市属事业单位招聘工作人员笔试真题
- 浙教版九年级数学同步训练:二次函数与几何结合压轴题(Ⅱ)(原卷版)
- 筒仓防雷施工方案
- 【地理】2024-2025学年人教版七年级下册地理背诵知识点
- 2025年上海工艺美术职业学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 23G409先张法预应力混凝土管桩
- 2024年宁波职业技术学院高职单招职业技能测验历年参考题库(频考版)含答案解析
- 《企业绩效考核工作探究的国内外文献综述》3200字
- 2024年江苏省中小学生金钥匙科技竞赛(高中组)考试题库(含答案)
- 上海交通大学学生生存手册
- 客户信用等级评定表(超实用)
评论
0/150
提交评论