东北大学软件学院15级计算机网络实验报告.docx
- 文档编号:29227741
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:22
- 大小:641.24KB
东北大学软件学院15级计算机网络实验报告.docx
《东北大学软件学院15级计算机网络实验报告.docx》由会员分享,可在线阅读,更多相关《东北大学软件学院15级计算机网络实验报告.docx(22页珍藏版)》请在冰豆网上搜索。
东北大学软件学院15级计算机网络实验报告
课程编号:
B080109003
网络应用程序设计
实践报告
姓名
学号
班级
软件1501
指导教师
费园园
实践课程名称
网络应用程序设计实践
开设学期
2016-2017第二学期
开设时间
第1周——第3周
报告日期
2017.03.17
评定成绩
评定人签字
评定日期
东北大学软件学院
1.实践目的
写出本次实践的目的,要求简洁清楚。
(1)理解FTP通信原理;
(2)学习使用Socket和多线程编写简单的FTP服务器;
(3)学习使用Sokcet编写简单的FTP客户端;
(4)理解HTTP通信原理;
(5)学习使用Socket编写HTTP服务器;
(6)学习使用Socket编写HTTP客户端;
(7)理解WebSocket的通信原理;
(8)使用tomcat服务器搭建多人聊天室;
2.预习内容
写出本次实践过程中你所用到的知识;
(1)FTP通信流程和通信命令
FTP使用2个端口,一个数据端口和一个命令端口(也叫做控制端口)。
这两个端口一般
是21(命令端口)和20(数据端口)。
(2)Socket编程
利用TCP协议进行通信的两个应用程序,server和client
交互过程:
1)服务器创建一个ServerSocket,然后调用accept方法等待客户连接
2)客户端程序创建一个socket并请求与服务器建立连接
3)在连接的socket上进行单独的线程对话
4)服务器开始等待新的连接请求(多线程)
(3)多线程编程
为了保证FTP服务器能够同时处理多个客户端的请求,服务器为每个客户端分配一个线程。
(4)HTTP通信原理
http的请求格式
http的应答模式
(5)WebSocket概念
在WebSocketAPI,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。
两者之间就直接可以数据互相传送。
在此WebSocket协议中,为我们实现即时服务带来了两大好处:
1.Header
互相沟通的Header是很小的-大概只有2Bytes
2.ServerPush
服务器的推送,服务器不再被动的接收到浏览器的request之后才返回数据,而是在有新数据时就主动推送给浏览器。
(6)WebSocket通信规则
1)客户端发起请求,服务器端创建一个ChatAnnotation对象,自动运行start方法,将Websocket会话对象session作为入参。
服务器端将当前ChatAnnotation对象加入到static的集合中。
2)客户端onopen方法自动运行。
3)客户端通过事件触发socket.send()方法,服务器端incoming方法自动运行,客户端发送的信息自动作为方法入参,服务器端可以遍历static的集合,把消息推送给所有的客户端。
4)收到推送消息后,客户端的onmessage方法自动运行。
5)客户端如果推出,客户端的onclose方法自动运行,接着服务器端的end方法自动运行,在end方法中,从static的集合中删除当前ChatAnnotation对象。
3.实践内容和实践过程
1.编写简单的FTP客户端程序;编写简单的FTP服务器程序
(1)实践内容
本实验要求完成以下功能(使用PASV模式):
功能名称
功能说明
优先级
获取文件列
表
给定用户工作目录,获得文件列表,包括文件名称,文件大小,文件创建时间
高
文件上传
上传文件到用户指定工作目录中
高
上传文件夹到用户指定工作目录中
低
支持断点续传
低
文件下载
给定用户工作目录,下载文件
高
给定用户工作目录,下载文件夹
低
支持断点续传
低
(2)实现过程
1)服务器创建一个ServerSocket,然后调用accept方法等待客户连接
2)客户端程序创建一个socket并请求与服务器建立连接
3)在连接的socket上进行单独的线程对话
客户端通过发送命令来使服务器做出相应的反应。
当发送PASV命令时候,服务器进入被动模式,并打开数据端口。
客户端连接数据端口,两者之间即可以通过命令端口处理请求,数据端口传输数据,比如文件(夹)的上传、下载。
上传:
将文件写进DataOutputStream输出流之中,流中的数据通过数据端口传输至服务器。
服务器端同样从数据端口获取流DataInputStream,并将其输出为文件。
此间需要传输文件的名字、大小等等参数。
文件夹的上传与下载:
类似于单文件操作。
首先遍历文件夹,获取文件的fileList集合,发送文件夹名字,在另一端新建同名文件夹。
循环发送所有文件,发送一个文件之后,另一端开始下载,下载完毕返回验证。
开始发送第二个文件,继续下载,直至所有文件传输完毕。
操作过程如流程图:
4)服务器开始等待新的连接请求(多线程)
下图为项目流程:
(3)关键技术
开启被动模式:
if(s.equals("PASV")){//如果是被动模式
if(pasvSocket!
=null){
pasvSocket.close();
}
try{
pasvSocket=newServerSocket(0);
intpPort=pasvSocket.getLocalPort();
if(pPort<1024){
pPort=1025;
}
response("227enteringpassivemode("+InetAddress.getLocalHost().getHostAddress().replace(',','.')
+","+pPort+")");
DataOutputStreamdataOutputStream=newDataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(InetAddress.getLocalHost().getHostAddress());
dataOutputStream.flush();
dataOutputStream.writeInt(pPort);
dataOutputStream.flush();
if(pasvSocket!
=null){
dataSocket=pasvSocket.accept();//阻塞
response("数据端口连接成功,继续输入命令:
");
}
}catch(Exceptione){
//TODOAuto-generatedcatchblock
if(pasvSocket!
=null){
pasvSocket.close();
pasvSocket=null;
}
}
return;
}
获取文件list:
if(s.equals("LIST")){
Filefile=newFile(this.currentDir);//路径名字
File[]files=file.listFiles();
Stringlist="";
for(inti=0;i longtime=files[i].lastModified(); Stringstime=newSimpleDateFormat("yyyy-MM-ddhh: mm: ss").format(newDate(time)); list+=files[i].getName()+"\t"+files[i].length()+"kb"+"\t"+stime+"\n";} DataOutputStreamdataOutputStream2=newDataOutputStream(dataSocket.getOutputStream()); dataOutputStream2.writeUTF(list); response("150来自数据端口的文件list: "); return; } 文件夹的传输: if(response_code.equals("153")){//RETR DataInputStreamdis=newDataInputStream(dataSocket.getInputStream()); StringdirName=dis.readUTF();//获取文件夹名字 System.out.println("文件夹的名字: "+dirName); Filefile=newFile(clientDir+"/"+dirName); file.mkdir(); intfileNum=dis.readInt();//获取文件的数量 System.out.println("文件的数量: "+fileNum); for(inti=0;i System.out.println(i); StringfileName=dis.readUTF();//获取文件的名字 longfileLength=dis.readLong(); FileOutputStreamfos=newFileOutputStream(newFile(clientDir+"/"+dirName+"/"+fileName)); byte[]sendBytes=newbyte[1024]; inttransLen=0; System.out.println(">>开始下载文件: "+fileName+",>>文件大小为: "+fileLength+"B----"); while(true){ intread=0; read=dis.read(sendBytes); if(read==-1){ break; } transLen+=read; fos.write(sendBytes,0,read); fos.flush(); if(transLen>=(int)fileLength){ break; } } System.out.println(">>下载文件: "+fileName+"成功>>"); DataOutputStreamdataOutputStream3=newDataOutputStream(dataSocket.getOutputStream()); dataOutputStream3.writeUTF("done"); dataOutputStream3.flush(); } System.out.println("文件夹"+dirName+"下载成功"); } (4)遇到的问题及解决方案 在处理文件夹传输的时候,遇到了一些问题: 上传多个文件,但是在服务器端仅仅收到一个文件,而且文件的大小是所有的文件的总和。 后来经过分析,发现是由于上传的时候使用的流操作,将所有文件顺序通过一个流操作进行传输,服务器端接收文件的时候会把流中的数据解析成文件,但是并不会把多个文件解析出来,最终导致所有的数据堆在一个文件之中。 解决方案: 在流程图中也可以看到文件夹的传输方式,现对客户端上传文件夹至服务器来进行说明。 客户端获取文件夹下在所有File对象,存为一个集合。 同时可以得到文件的数量等等基本属性,客户端将这些信息发送至服务器,服务器按照指令创建文件夹。 接着客户端发送第一个文件,而后暂停(readline()方法阻塞进程)。 服务器开始接收第一个文件,接收完毕发送一道指令给客户端,readline()方法执行之后,进入下个循环发送第二个文件。 直至所有文件循环结束。 上传文件夹完毕。 2.编写简单的HTTP1.1客户端程序;编写简单的HTTP1.1服务器程序; (1)实践内容 功能名称 功能说明 优先级 服务器功能 提供HTML,JPG等MIME类型的资源 高 客户端功能 访问服务器,获取HTML和JPG资源,保存到本地磁盘 高 访问服务器,获取WMV等其他资源类型,保存到本地磁盘 低 (2)实现过程 (3)关键技术 连接socket端口: Socketsocket=newSocket("localhost",8081); 客户端发送HTTP请求: PrintWriterwriter=newPrintWriter(socket.getOutputStream()); DataOutputStreamdataOutputStream=newDataOutputStream(socket.getOutputStream()); StringfileName="final_travel/index.html"; //发送请求头GET方式中,请求数据挂在URL后,POST方式中,请求数据放在请求体中 writer.println("GET"+fileName+"HTTP/1.1"); writer.println("Host: localhost"); writer.println("connection: keep-alive"); writer.println();//空行 writer.flush(); 客户端接收服务器返回的资源: InputStreaminputStream=socket.getInputStream(); BufferedReaderreader=newBufferedReader(newInputStreamReader(inputStream)); StringfirstLineOfResponse=reader.readLine();//HTTP/1.1200OK System.out.println(firstLineOfResponse); StringsecondLineOfResponse=reader.readLine();//Content-Type: image/jpg System.out.println(secondLineOfResponse); StringthirdLineOfResponse=reader.readLine();//Content-Length: System.out.println(thirdLineOfResponse); StringfourthLineOfResponse=reader.readLine();//空行 byte[]b=newbyte[1024]; StringrealFileName=fileName; if(fileName.contains("/")){//处理类似于文件夹/文件.后缀类型的文件 String[]num=fileName.split("/"); realFileName=num[num.length-1]; } FileOutputStreamout=newFileOutputStream("/home/scc/eclipse/workspaces/experient_2/client"+"/"+realFileName); Stringstring=out.toString(); System.out.println(string); intlen=inputStream.read(b); while(len! =-1) { out.write(b,0,len); len=inputStream.read(b); } inputStream.close(); out.close(); (4)遇到的问题及解决方案 问题: 客户端与服务器进行通讯时候,使用流操作来传输数据,出现返回文件偶尔出错的现象。 解决方案: 每次客户端接收完数据之后,都将HTTP连接断开,需要时候再进行连接。 3.编写Websocket聊天室功能,包括客户端JavaScript和服务器端Servlet (1)实践内容 本实验要求完成以下功能: 功能名称 功能说明 优先级 完成度 多人聊天 在网页上实现多人聊天 高 多人聊天 跟某个人聊天 用户登录,显示在线列表,指定和某个人聊天 中 用户登录,显示在线列表,指定和某个人聊天 在线客服 在线客服功能 低 未完成 (2)实现过程 客户端与服务器建立连接并进行第一条通讯的流程图: 群发消息的通讯流程: 显示在线列表的实现流程: 私聊功能,以文字形式描述如下: 用户1发送消息,格式为+&用户2昵称。 服务端识别之后,将用户1的私聊对象talkTo属性设置为用户2,isPrivateChat属性设置为true。 根据提供的用户名,获取到用户2的chatAnontation,并将用户2的私聊对象talkTo属性设置为用户1,isPrivateChat属性设置为true。 因此可以实现: 当进入私聊模式后,用户1或者用户2发送一条消息,在后台判断isPrivateChat,如果为true,那么将根据该用户的talkTo属性存储的用户名获取到私聊对象的session,只将消息广播给特定私聊对象。 当退出私聊模式时候,一方输入-&即可,后台清除用户1和用户2的talkTo属性,并将isPrivateChat均设置为false。 从而结束私聊模式,今后发送消息均为群聊消息,广播给所有的在线用户。 (3)关键技术 显示在线列表的实现: 当用户连接或者断开时,均会执行以下方法(核心代码): 首先将所有的用户信息获取到,封装成一个JSON对象,将JSON格式的字符串广播出去 JSONObjectjsonObject_send=newJSONObject(); JSONArrayjsonArray_send=newJSONArray(); for(Useruser2: users){ jsonArray_send.put(user2.getName()); } try{ jsonObject_send.put("list",jsonArray_send); }catch(JSONExceptione){ e.printStackTrace(); } listbroadcast(jsonObject_send.toString()); 广播List的方法 privatestaticvoidlistbroadcast(Stringmsg){ for(ChatAnnotationclient: connections){//每个客户端都发送一遍 try{ synchronized(client){ client.session.getBasicRemote().sendText("list"+msg); } }catch(IOExceptione){ System.out.println("在线列表显示出错"); } } } 前端解析如下: 过程为先将接收到的消息进行过滤,如果为用于更新list的消息,则进行解析。 将获取到的字符串转换成一个JSON对象,解析整个JSON对象,获取到在线列表,输出到列表框中。 varreceivedMsg=message.data; if(receivedMsg.startsWith("list")){ receivedMsg=receivedMsg.substring(4); varobj=JSON.parse(receivedMsg); varprint=" for(vari=0;i print=print+" } print=print+""; document.getElementById("listbox").innerHTML=print; 私聊功能: 后台接收到要进行私聊的命令,过滤之后得到talkToName,设置当前用户的TalkTo、PrivateChat属性。 遍历users集合,获取到要私聊对象的user类,将其TalkTo、PrivateChat属性也进行相应的设置,同是私聊对象的chatAnnotation将作为参数传至广播方法privateBroadcast(String,ChatAnnotation)。 if(message.startsWith("+&")){ StringtalkToName=message.substring (2);//获得想要私聊的对象名字 user.setTalkTo(talkToName); user.setPrivateChat(true); System.out.println("talkToName"+talkToName); ChatAnnotationchatAnnotation=null; for(inti=0;i if(users.get(i).getName().equals(talkToName)){ users.get(i).setTalkTo(
";
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 东北大学 软件 学院 15 计算机网络 实验 报告