网络文件传输设计报告Word格式.docx
- 文档编号:17103575
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:20
- 大小:265.57KB
网络文件传输设计报告Word格式.docx
《网络文件传输设计报告Word格式.docx》由会员分享,可在线阅读,更多相关《网络文件传输设计报告Word格式.docx(20页珍藏版)》请在冰豆网上搜索。
2)刷新用户列表时发送的多播数据包和启动的一样,只是在发送数据包前,将本机的用户列表清空,重新建立新的用户列表。
3)传送聊天信息时同样使用UDP协议。
由于UDP协议是无连接协议,传输速度快,但是没有确认机制,是不可靠的协议,需要自己定义返回信息的标志来判断对方是否收到信息。
4)用户离线时发送一个离线多播数据包到236.136.25.7,收到此多播包的用户,根据包中的IP地址删除对方的用户列表信息。
5)传送文件和文件夹是使用TCP协议,端口3608。
TCP是一种面向连接的服务,在文件传输时会先行建立连接,通过链接提供双向、有序且无重复的数据流服务、以及流量控制、差错检测和纠错等服务,从而确保文件传输的正确性。
2.功能设计
在C/S体系结构下,设计局域网文件传送的网络传输软件。
功能包括局域网文件传送和局域网简单文字聊天,可以同时对多个用户发送文件,以及传送文件功能不分目录与文件,均统一传送,让用户使用起来更方便。
1)C/S(Client/Server)结构,即客户机和服务器结构。
它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理的分配到Client端和Server端来实现,降低了系统的通讯开销。
Client和Server常常分别处在相距很远的两台计算机上,Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户;
Server程序的任务是接受Client程序提出的服务请求,进行相应的处理,再将结果返回给Client程序。
图2.1C/S结构
2)Java的网络编程
Java程序通过.Socket和.ServerSocket在两台主机之间建立I/O数据连接流,文件以字节流的形式从一台主机传送到另一台主机。
在TCP/IP参考模型中,应用程序处在应用层,应用层下面分别是传输层、网络互连层、主机-网络层。
传输层的功能是使源主机和目标主机上的进程可以进行对话。
在传输层定义了两种服务质量不同的协议,即TCP(TransmissionControlProtocol,传输控制协议)和UDP(UserDatagramProtocol,用户数据包协议)。
TCP协议是一种面向连接的、可靠的协议,主要适用于需要保证数据准确性的场合。
UDP协议是一个不可靠的、无连接协议,主要适用于不需要对报文进行排序和流量控制的场合。
.Socket与.ServerSocket建立在TCP协议的基础上,可靠性好,可用来传送文件。
.DatagramSocket与.DatagramPacket是建立在UDP协议的基础上,可用来在局域网中广播本地主机的IP地址。
3)Java的多线程
Java程序通过java.lang.Thread和java.lang.Runnable来实现程序的多线程。
Java虚拟机允许应用程序并发地运行多个执行线程。
服务器端创建多个服务线程,便可以同时接受多个来自客户端的请求,并给予回应。
从而实现同时向多个用户传送文件的功能。
4)Java的异常控制
Java语言中的所有异常都是由Throwable类继承而来,但在下一层分为两个分支:
Error和Exception。
Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。
应用程序不应该抛出这种类型的对象。
我们在进行Java程序设计的时候,只需要关注Exception层次结构。
这个层次结构又分解为两个分支:
一个分支是派生于RuntimeException的异常;
另一个分支包含其他异常。
由程序错误导致的异常属于RuntimeException;
曾经能够正确运行,而由于某些情况导致的异常不属于RuntimeException。
Java的方法可以抛出一个异常,不予解决;
也可以catch一个异常,并给予处理的方法。
图2.2Java中的异常层次结构
4.详细设计
网络文件传输系统的核心部分为服务器端的线程组测监听等待客户端的连接进行通信。
系统启动的时候,接收端线程首先启动,等待客户端的链接,客户端启动后根据IP地址会自动链接到相应的服务器上进行通信。
1)服务器端的阻塞等待状态
图2.3服务器端的线程等待
2)客户端的线程启动连接
图2.4客户端的线程启动
3)客户端选择要传输的文件的路径
图2.5路径指定后文件传输
4)接受端接受文件成功默认保存在源码文件夹下
图2.6文件接受端的文件接受成功
5)当一端失去链接后进行的异常处理
图2.7异常处理
6)类图
图2.8程序类图
三.调试及测试
1、调试过程中遇到的主要问题及解决方法
1)文件的路径问题,当显示要传输的文件时,直接发送一个文件路径即可,通过FILE()函数可以直接构造出一个文件实例,然后即可对文件进行操作。
2)文件传输结束标志,文件什么时候传输完毕,什么时候退出SOCKET,不再进行数据的收发,我们可以在传输文件前的通信中把文件大小告诉接收方,当接收方写入文件数据到了该大小后传输结束。
3)文件传输过程中出现发送方与接收方单方中断传输时候,如何通知对方结束程序。
接收端暂停接收文件,将发送暂停的消息给发送端,发送端使用join()方法暂停该写线程;
若接收端继续接收,将发送继续的消息给发送端,发送端使用interrupt()方法结束join()方法,发送端继续发送;
若接收端终止接收,将发送终止的消息给发送端,发送端终止发送。
4)文件内容的压缩与不压缩一定程度上影响了文件传输的逻辑结构,采取不同的压缩方式,在不同的阶段进行压缩,文件传输的逻辑结构应该不同,这样才能保证传输数据的正确性和传输的高效性。
5)在文件传输过程中是否会有丢包的现象呢?
采取TCP方式,由于它是可靠的连接,三次握手机制保证了传输数据的正确性。
而采取UDP方式就不行了。
6)通过构造服务器端套接字实现阻塞等待的结果。
然后用选择器和通道链接实现服务器和客户端的链接。
当通道链接好后,文件传输用字节流进行传输。
2、对设计和编码的回顾讨论和分析
本系统应该实现的功能基本已实现,但还是有一点瑕疵没有解决。
例如,程序正常结束时,有时会出现IO异常;
有时电脑没连接局域网,启动程序后出现加入多播组错误。
3、程序运行的性能及效率分析
1)传输速度
文件传输速度是指文件的实际内容开始发送到文件内容全部传输完毕所用的时间来除文件的大小得出的值。
这个值由发送数据包的大小决定,这个大小值要保证一次传输数据要尽可能的多的同时发送数据包的速度也要快,也就是说网络占用率与传输速度相互关联。
程序中我们使用TCP进行文件的传输,并规定了每次传送的字节数1024,这样既做到了速率上的大大改进,使传输速率更高,从而也使该网络文件传输系统实现了性能上的提高。
1)网络资源的使用率
网络资源的利用率是指在文件传输过程中,对网络资源的利用情况,SOCKET在传输数据包的时候有一个最大传输字节,可以用SND_BUF、RCV_BUF分别取出发送端与接收端的最大值。
每次发送数据包时候最大利用了SND_BUF、RCV_BUF的大小,就可以使传输效率大大提高,网络利用率也就很高。
网络资源的使用率也影响文件数据的传输速率。
为了保证每次发包与收包的数据大小的一致性,我们保证了接收端的RCV_BUF与发送端的SND_BUF相等。
3)用户使用
首先,刷新功能采用基于UDP协议的局域网多播和启动线程执行,使刷新速度更加快速;
其次,用户发送文件后,会反馈文件发送接受情况。
如果发送成功,用户可以考虑下线;
如果发送失败,则要提醒发送方失败信息。
4)使用范围
网络文件传输系统是我们在windows系统下开发的一款文件传输系统,能够实现windows系统下用户之间的文件传输。
四、经验和体会
通过本次Java语言课程设计,使我对面向对象的程序设计有了很大程度的掌握,它将重点放在对象与对象的接口上,与传统的面向过程程序设计有着很大的不同。
就我所做的网络文件传输系统而言,主要用到Java的网络编程,网络编程包括UDP和TCP,UDP是不可靠的传输负责消息的传送,而TCP是可靠的传输负责文件的传输;
多线程的运用实现了一个用户可以向多个用户传送文件,使本系统的功能更加完善;
文件流、对象流的使用使得程序在读取文件与对象方便提供了很大的便捷;
另外,程序中增加了对异常的处理方法,增强了程序的鲁棒性(Robust);
还有系统界面的设计也花费了很大的功夫。
虽然在完成本系统的过程中遇到很多问题,经过自己的反复调试,另外在老师的指导和与同学的讨论,很多问题都解决了。
同时在解决问题的过程中,自己对很多知识都有了进一步的了解;
也让我知道了自己哪些地方的不足,在以后的学习中会加强该方面的学习。
在此,我想感谢我的指导老师对我的指导与帮助,还有帮助我的同学们。
附录:
源程序
/*
*首先定义文件传输的信息,比如块信息,传输命令,缓冲区信息等。
*/
importjava.nio.ByteBuffer;
publicclassFileUtil{
privatebyteFileInfo=0x1;
///文件信息上传命令
privatebyteFileDB=0x2;
///文件数据传输命令
privateintBlockSize=512;
///规定文件块大小为512
publicbyte[]getFileInfoPack(StringFileName,intFileSize){
ByteBufferbuf=ByteBuffer.allocate(260);
//分配一个新的字节缓冲区
byte[]infopack=newbyte[260];
byte[]filename=newbyte[255];
System.arraycopy(FileName.getBytes(),0,filename,0,FileName.length());
//从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
buf.clear();
buf.put(FileInfo);
//相对put方法(可选操作),将给定的字节写入此缓冲区的当前位置,然后该位置递增。
buf.putInt(FileSize);
//用于写入int值的相对put方法(可选操作),
//将4个包含给定int值的字节按照当前的字节顺序写入到此缓冲区的当前位置,然后将该位置增加4。
buf.put(filename);
buf.flip();
buf.get(infopack);
//此方法将此缓冲区的字节传输到给定的目标数组中
pact();
//将缓冲区的当前位置和界限之间的字节(如果有)复制到缓冲区的开始处
returninfopack;
}
publicbyte[]getFileDB(intindex,intblocksize,byte[]data){
byte[]filedb=newbyte[9+blocksize];
//对文件本身的传输过程定义
ByteBufferbuf=ByteBuffer.allocate(9+blocksize);
buf.put(this.FileDB);
buf.putInt(index);
buf.putInt(blocksize);
buf.put(data,0,blocksize);
buf.get(filedb);
returnfiledb;
publicintgetBlockSize(){
returnthis.BlockSize;
}
*文件接受端线程的过程。
importjava.nio.channels.SocketChannel;
importjava.nio.channels.SelectionKey;
importjava.nio.channels.Selector;
importjava.io.RandomAccessFile;
importjava.io.FileOutputStream;
importjava.io.File;
importjava.io.IOException;
importjava.nio.channels.ClosedChannelException;
publicclassReveiceThreadextendsThread{
privateFileUtilutil=newFileUtil();
/*
*针对面向流的连接套接字的可选择通道。
*/
privateSocketChannelr_channel=null;
//
privateByteBufferbuf=ByteBuffer.allocate(util.getBlockSize()+9);
publicReveiceThread(SocketChannelchannel)throwsException{
this.r_channel=channel;
this.r_channel.configureBlocking(false);
publicvoidrun(){
try{
Selectorselector=Selector.open();
SelectionKeykey=r_channel.register(selector,SelectionKey.OP_READ);
Filefile=null;
FileOutputStreamfout=null;
//文件输出流对象
RandomAccessFileraf=null;
//创建临时文件对象
intFileSize=0;
//文件大小
StringFileName="
"
;
//文件名称
intBlockIndex=0;
//文件块索引号
intBlockSize=0;
//文件块大小
intreadlen=0;
//读到的数据长度
intbuflen=0;
//buf的长度
bytecmd=0x0;
//命令码
intBlockNum=0;
//文件块数据计数器
intCompSize=0;
//已经完成数
while(key.selector().isOpen()){
intselkey=selector.select();
if(selkey==0){
readlen=this.r_channel.read(buf);
//开始读数据
buflen+=readlen;
//记录缓冲区buf的长度
if(readlen>
=1){//读到了数据
buf.rewind();
///数据指针指到0
cmd=buf.get();
//读取一个字节,获得文件头信息,判断发送信息类型(headorbody)
switch(cmd){
case0x1:
{///文件信息
if(buflen>
=260){
FileSize=buf.getInt();
//获取文件大小
buf.get(filename);
//从缓冲区中读取255个字节,获取文件名
FileName=(newString(filename)).trim();
//删除读取过的数据
buflen-=260;
//缓冲区大小减去已读的260个字节大小
buf.position(buflen);
//数据指针指向buf的最后位置
System.out.println("
文件名-->
:
+FileName+"
文件大小-->
+
FileSize);
fout=newFileOutputStream(FileName);
file=newFile("
~"
.tmp"
);
//创建临时文件
raf=newRandomAccessFile(file,"
rw"
//向临时文件中写入数据
文件创建成功,开始写入数据..."
else{
///数据指针指向buf的最后位置
break;
case0x2:
{//文件主体数据(body)
=9){
BlockIndex=buf.getInt();
//获得文件块索引号
BlockSize=buf.getInt();
//获得文件块大小
=(9+BlockSize)){//缓冲区大小减去已读数据
byte[]blockdb=newbyte[BlockSize];
buf.get(blockdb);
//读取文件块数据
//删除已读数据
buflen-=(9+BlockSize);
//数据指针指向buf缓冲区最后位置
if(BlockSize<
util.getBlockSize()){
//如果收到的数据块大小小于定义的最大文件块大小
byte[]tmpdb=newbyte[util.getBlockSize()];
///定义临时最大数据块
System.arraycopy(blockdb,0,tmpdb,0,BlockSize);
//
raf.seek((util.getBlockSize()+4)*BlockIndex);
//(+4)是用于存放文件大小信息的
//文件块写入临时文件中将相应数据块放到相应的位置中去
raf.writeInt(BlockSize);
//向临时数据块中写入文件大小信息
raf.write(tmpdb);
//向临时数据块中写入文件块信息
BlockNum++;
//文件块计数器累加
//收到的数据等于文件块定义的最大值
raf.write(blockdb);
//文件块计数器累加
写入临时文件完成:
---->
(CompSize+=BlockSize)+"
****"
FileSize-=BlockSize;
///每收到一块,就从总文件大小里减去
if(FileSize==0){///如果减到0了,说明文件块已经收全了,可以关闭文件了。
for(inti=0;
i<
BlockNum;
i++){
//根据文件块个数循环将临时文件写入正式文件
raf.seek((util.getBlockSize()+4)*i);
BlockSize=raf.readInt();
//从临时文件中读取文件块大小
byte[]tmpdb=newbyte[BlockSize];
raf.read(tmpdb);
//从临时文件中读取文件块数据
fout.write(tmpdb);
//向正式文件中写入文件块
raf.close();
//释放资源
file.delete();
///删除临时文件
fout.close();
*******文件已经接收完成了!
*******"
catch(ClosedChannelExceptionex){
发生ClosedChannelException异常,原因---->
:
+ex.getMessage());
catch(IOExceptionex){
打开选择器时异常,原因---->
*文件接受端线程的套接字启动及接受数据。
import.SocketAddress;
import.InetSocke
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 文件传输 设计 报告