互联网程序设计第四讲

第四讲 网络文件传送程序设计

完成日期:2018.10.10
GitHub:https://github.com/fyinh/network_programming_course/tree/master/ch04


教学与实践目的:学会基本的文件传输FTP程序设计技术。
  进一步学习TCP套接字,利用它的字节传输技术,实现网络文件传输。

  文件传输协议规定(RFC 959 FTP.txt),网络文件传输中用两个TCP端口来实现:

  • 一个端口(21号)用来对话,传递控制信息,总是开启;
  • 一个端口(20号)实现文件数据传递服务,有数据传输服务时开启。
    在这里插入图片描述
      本实验实现一个简约的远程文件传输系统,方便教学资料的下载。
      用2021端口实现对话服务,如身份验证、文件目录信息浏览等,用2020端口传递数据文件(即文件上传下载)。

基于C/S软件架构的主要程序模块如下:
客户端程序有:
主界面客户端程序FileClientJFrame.java;
文件对话客户端程序(控制进程)FileDialogClient.java;
文件数据客户端程序(数据传输进程)FileDataClient.java。

服务端程序:
文件对话服务器程序FileDialogServer.java,开启2021端口;
主要功能:身份验证、文件目录传送。
文件数据服务器程序FileDataServer.java,开启2020端口。
主要功能:
根据请求的文件名传送文件,接收文件。

一、程序设计第一步

设计任务:

  创建远程文件对话程序
  客户端程序主要功能:发送用户信息,浏览文件目录,实现和文件服务器的基本对话。

过程:

1. 新建一个程序包:ftpClient,用于存放远程文件操作相关的程序。
2. 将TCPClient.java程序重构、复制、并命名为FileDialogClient.java,原有的方法保持不变。
3. 用户界面程序FileClientJFrame.java如下图所示。
在这里插入图片描述
(1)重构、复制TCPClientThreadJFrame、并命名为FileClientJFrame,新增“下载”和“上传”2个按钮;
(2)运行程序FileClientJFrame,效果是否如图2;
(3)申明FileDialogClient对象,并定义2个全局变量:ip, port;
(4)在界面的“连接”按钮中实例化FileDialogClient对象,并定义和启动“读”线程;
(5)在界面的“发送”按钮中调用FileDialogClient.java的发送方法;
(6)在界面的“退出”按钮中调用FileDialogClient.java的关闭方法。
(7)运行窗口程序,输入一个公用的FTP服务器的地址,连接成功后发送一些基本FTP命令,观察返回结果;
(8)新增快捷功能:
在用户界面设计状态,鼠标右击信息显示区,选择“事件”、“MouseMotion”、“mousedragged”,键入如下代码:

jTextField1.setText(jTextArea1.getSelectedText());
//鼠标加亮的字符串会自动出现在信息录入行中。

二、程序设计第二步

  创建客户端数据传送进程FileDataClient.java
主要功能:
连接服务器数据端口、发送文件名、保存下载的文件或上传文件,文件传输完成后关闭数据连接。

过程:

(1)构造方法,FileDataClient(String ip,String port),主要功能是向服务器的数据端口请求连接;
(2)文件下载方法fileGet(fileName)[见附录代码]。
  主要功能是准备当地磁盘空文件,向服务器发送文件名(基于字符串输出流操作),然后接收网络文件数据并保存当地磁盘(基于字节流操作),关闭数据套接字。
在界面的“下载”按钮中调用该方法,如:

String fName=jTextField1.getText();
jTextField1.setText("");
new FileDataClient(ip,port).fileGet(fName);

注意,可能存在的问题:
  若下载文件不成功,可在此行设置断点,查看3个变量ip, port fName的值是否符合预期; 检查你连接的数据端口是否减“1”了;
  若文件是空,第一要检查文件关闭操作是否完成。

(3)文件上传方法filePut()[选做],主要功能是向服务器发送文件名,发送文件数据,关闭数据套接字。
在主界面的“上传”按钮中调用该方法。

new FileDataClient(ip,port).filePut();

三、程序设计第三步:

  对话服务器程序FileDialogServer.java
  对话服务器程序开启2021端口,用来传送双方的对话信息,如文件目录等信息。

四、程序设计第四步:

  数据服务器端程序FileDataServer.java
  数据传输程序专门提供文件上传和下载服务,开启2020端口,提供文件下载服务。

附录1:客户程序数据进程中的文件下载模块

	public String fileGet(String fName) throws IOException{
        boolean flag = false;
        if(dataSocket != null){
            byte[] buff = new byte[1024 * 2];
            // (1)文件保存对话框.
            JFileChooser chooser = new JFileChooser();
            File saveFile = new File(fName);
            chooser.setSelectedFile(saveFile);
            int stat = chooser.showSaveDialog(null);
            if(stat == JFileChooser.APPROVE_OPTION)
                saveFile = chooser.getSelectedFile();
            else
                saveFile = null;
            if(saveFile != null){
                FileOutputStream fileOut=new FileOutputStream(saveFile); //新建本地空文件.
                InputStream socketIn= dataSocket.getInputStream();//网络字节输入流
                OutputStream socketOut=dataSocket.getOutputStream();//网络字节数出流
                //(2)发送请求的文件名,字符串读写功能 
                PrintWriter pw = new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true);
                pw.println(fName);
                
                //(3)接收服务器的数据文件,字节读写功能
                int len=socketIn.read(buff);//读一块到缓冲区.
                while(len != -1){
                fileOut.write(buff,0,len);//写一块到文件.
                len=socketIn.read(buff);
                flag=true;
                }
                //(4)文件传输完毕,关闭数据套接字。
                fileOut.close();
                //JOptionPane.showMessageDialog(null, "文件接收完毕.");
                dataSocket.close();
                if(flag)
                    return "文件下载成功.";
                else{
                    saveFile.delete();
                    return "文件名错误或文件下载失败.";
                }
            }else{
                dataSocket.close();
                return "本地文件创建失败.";
            }
        }else
            return "服务器连接失败.";
    }

附录2:服务器对话服务程序中的文件目录服务模块(供参考):

pw.println("可供下载的文件如下:");
String fName1="E:\\";//给出下载目录路经
File f=new File(fName1);
String[] s=f.list();//获得目录下所有的子目录和文件名.
int len=s.length;
int n=0;
long filelength=0;
File temp;
while(n<len){
	temp=new File(f+"\\"+s[n]);
    if(temp.isFile()){
    	filelength=temp.length()/1024;//字节单位KB
        pw.println(s[n]+" ["+filelength+"KB]");
   }else
   pw.println(s[n]+" [DIR]");
   n++;
}
pw.println("************文件下载********************");
pw.println("输入文件全名,点击下载按钮,退出输入bye");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值