【转贴自http://www.java-cn.com,原贴见http://www.java-cn.com/technology/technology_detail.jsp?id=1588】
Java的网络编程:用Java实现FTP服务器 作者:谷和启 本文选自:开放系统世界??赛迪网 2002年12月27日 FTP(File Transfer Protocol 文件传输协议)是Internet 上用来传送文件的协议。在Internet上通过FTP 服务器可以进行文件的上传(Upload)或下载(Download)。FTP是实时联机服务,在使用它之前必须是具有该服务的一个用户(用户名和口令),工作时客户端必须先登录到作为服务器一方的计算机上,用户登录后可以进行文件搜索和文件传送等有关操作,如改变当前工作目录、列文件目录、设置传输参数及传送文件等。使用FTP可以传送所有类型的文件,如文本文件、二进制可执行文件、图象文件、声音文件和数据压缩文件等。 FTP 命令 FTP 的主要操作都是基于各种命令基础之上的。常用的命令有: ◆ 设置传输模式,它包括ASCⅡ(文本) 和BINARY 二进制模式; ◆ 目录操作,改变或显示远程计算机的当前目录(cd、dir/ls 命令); ◆ 连接操作,open命令用于建立同远程计算机的连接;close命令用于关闭连接; ◆ 发送操作,put命令用于传送文件到远程计算机;mput 命令用于传送多个文件到远程计算机; ◆ 获取操作,get命令用于接收一个文件;mget命令用于接收多个文件。 编程思路 根据FTP 的工作原理,在主函数中建立一个服务器套接字端口,等待客户端请求,一旦客户端请求被接受,服务器程序就建立一个服务器分线程,处理客户端的命令。如果客户端需要和服务器端进行文件的传输,则建立一个新的套接字连接来完成文件的操作。 编程技巧说明 1.主函数设计 在主函数中,完成服务器端口的侦听和服务线程的创建。我们利用一个静态字符串变量initDir 来保存服务器线程运行时所在的工作目录。服务器的初始工作目录是由程序运行时用户输入的,缺省为C盘的根目录。 具体的代码如下: public class ftpServer extends Thread{ private Socket socketClient; private int counter; private static String initDir; public static void main(String[] args){ if(args.length != 0) { initDir = args[0]; }else{ initDir = "c:";} int i = 1; try{ System.out.println("ftp server started!"); //监听21号端口 ServerSocket s = new ServerSocket(21); for(;;){ //接受客户端请求 Socket incoming = s.accept(); //创建服务线程 new ftpServer(incoming,i).start(); i++; } }catch(Exception e){} } 2. 线程类的设计 线程类的主要设计都是在run()方法中实现。用run()方法得到客户端的套接字信息,根据套接字得到输入流和输出流,向客户端发送欢迎信息。 3. FTP 命令的处理 (1) 访问控制命令 ◆ user name(user) 和 password (pass) 命令处理代码如下: if(str.startsWith("USER")){ user = str.substring(4); user = user.trim(); out.println("331 Password");} if(str.startsWith("PASS")) out.println("230 User "+user+" logged in."); User 命令和 Password 命令分别用来提交客户端用户输入的用户名和口令。 ◆ CWD (CHANGE WORKING DIRECTORY) 命令处理代码如下: if(str.startsWith("CWD")){ String str1 = str.substring(3); dir = dir+"/"+str1.trim(); out.println("250 CWD command succesful"); } 该命令改变工作目录到用户指定的目录。 ◆ CDUP (CHANGE TO PARENT DIRECTORY) 命令处理代码如下: if(str.startsWith("CDUP")){ int n = dir.lastIndexOf("/"); dir = dir.substring(0,n); out.println("250 CWD command succesful"); } 该命令改变当前目录为上一层目录。 ◆ QUIT命令处理代码如下: if(str.startsWith("QUIT")) { out.println("GOOD BYE"); done = true; } 该命令退出及关闭与服务器的连接,输出GOOD BYE。 (2) 传输参数命令 ◆ Port命令处理代码如下: if(str.startsWith("PORT")) { out.println("200 PORT command successful"); int i = str.length() - 1; int j = str.lastIndexOf(","); int k = str.lastIndexOf(",",j-1); String str1,str2; str1=""; str2=""; for(int l=k+1;l<j;l++){ str1 = str2 + str.charAt(l); } for(int l=j+1;l<=i;l++){ str2 = str2 + str.charAt(l); } tempPort = Integer.parseInt(str1) * 16 *16 +Integer.parseInt(str2); } 使用该命令时,客户端必须发送客户端用于接收数据的32位IP 地址和16位 的TCP 端口号。这些信息以8位为一组,使用十进制传输,中间用逗号隔开。 ◆ TYPE命令处理代码如下: if(str.startsWith("TYPE")){ out.println("200 type set"); } TYPE 命令用来完成类型设置。 (3) FTP 服务命令 ◆ RETR (RETEIEVE) 和 STORE (STORE)命令处理的代码 if(str.startsWith("RETR")){ out.println("150 Binary data connection"); str = str.substring(4); str = str.trim(); RandomAccessFile outFile = new RandomAccessFile(dir+"/"+str,"r"); Socket tempSocket = new Socket(host,tempPort); OutputStream outSocket = tempSocket.getOutputStream(); byte byteBuffer[]= new byte[1024]; int amount; try{ while((amount = outFile.read(byteBuffer)) != -1){ outSocket.write(byteBuffer, 0, amount); } outSocket.close(); out.println("226 transfer complete"); outFile.close(); tempSocket.close(); } catch(IOException e){} } if(str.startsWith("STOR")){ out.println("150 Binary data connection"); str = str.substring(4); str = str.trim(); RandomAccessFile inFile = new RandomAccessFile(dir+"/"+str,"rw"); Socket tempSocket = new Socket(host,tempPort); InputStream inSocket = tempSocket.getInputStream(); byte byteBuffer[] = new byte[1024]; int amount; try{ while((amount =inSocket.read(byteBuffer) )!= -1){ inFile.write(byteBuffer, 0, amount); } inSocket.close(); out.println("226 transfer complete"); inFile.close(); tempSocket.close(); } catch(IOException e){} } 文件传输命令包括从服务器中获得文件RETR和向服务器中发送文件STOR,这两个命令的处理非常类似。处理RETR命令时,首先得到用户要获得的文件的名称,根据名称创建一个文件输入流,然后和客户端建立临时套接字连接,并得到一个输出流。随后,将文件输入流中的数据读出并借助于套接字输出流发送到客户端,传输完毕以后,关闭流和临时套接字。 STOR 命令的处理也是同样的过程,只是方向正好相反。 ◆ DELE (DELETE)命令处理代码如下: if(str.startsWith("DELE")){ str = str.substring(4); str = str.trim(); File file = new File(dir,str); boolean del = file.delete(); out.println("250 delete command successful"); } DELE 命令用于删除服务器上的指定文件。 ◆ LIST命令处理代码如下: if(str.startsWith("LIST")) { try{ out.println("150 ASCII data"); Socket tempSocket = new Socket(host,tempPort); PrintWriter out2= new PrintWriter(tempSocket.getOutputStream(),true); File file = new File(dir); String[] dirStructure = new String[10]; dirStructure= file.list(); String strType=""; for(int i=0;i<dirStructure.length;i++){ if( dirStructure[i].indexOf(".") == -1) { strType = "d ";} else {strType = "- ";} out2.println(strType+dirStructure[i]); } tempSocket.close(); out.println("226 transfer complete"); } catch(IOException e){} LIST 命令用于向客户端返回服务器中工作目录下的目录结构,包括文件和目录的列表。处理这个命令时,先创建一个临时的套接字向客户端发送目录信息。这个套接字的目的端口号缺省为1,然后为当前工作目录创建File 对象,利用该对象的list()方法得到一个包含该目录下所有文件和子目录名称的字符串数组,然后根据名称中是否含有文件名中特有的“.”来区别目录和文件。最后,将得到的名称数组通过临时套接字发送到客户端。 (责任编辑 Sunny) 
原作者: 谷和启 
原出处: 赛迪网

解决方案 »

  1.   

    【转贴自http://www.java-cn.com,原贴见http://www.java-cn.com/technology/technology_detail.jsp?id=1588】
    Java的网络编程:用Java实现FTP服务器 作者:谷和启 本文选自:开放系统世界??赛迪网 2002年12月27日 FTP(File Transfer Protocol 文件传输协议)是Internet 上用来传送文件的协议。在Internet上通过FTP 服务器可以进行文件的上传(Upload)或下载(Download)。FTP是实时联机服务,在使用它之前必须是具有该服务的一个用户(用户名和口令),工作时客户端必须先登录到作为服务器一方的计算机上,用户登录后可以进行文件搜索和文件传送等有关操作,如改变当前工作目录、列文件目录、设置传输参数及传送文件等。使用FTP可以传送所有类型的文件,如文本文件、二进制可执行文件、图象文件、声音文件和数据压缩文件等。 FTP 命令 FTP 的主要操作都是基于各种命令基础之上的。常用的命令有: ◆ 设置传输模式,它包括ASCⅡ(文本) 和BINARY 二进制模式; ◆ 目录操作,改变或显示远程计算机的当前目录(cd、dir/ls 命令); ◆ 连接操作,open命令用于建立同远程计算机的连接;close命令用于关闭连接; ◆ 发送操作,put命令用于传送文件到远程计算机;mput 命令用于传送多个文件到远程计算机; ◆ 获取操作,get命令用于接收一个文件;mget命令用于接收多个文件。 编程思路 根据FTP 的工作原理,在主函数中建立一个服务器套接字端口,等待客户端请求,一旦客户端请求被接受,服务器程序就建立一个服务器分线程,处理客户端的命令。如果客户端需要和服务器端进行文件的传输,则建立一个新的套接字连接来完成文件的操作。 编程技巧说明 1.主函数设计 在主函数中,完成服务器端口的侦听和服务线程的创建。我们利用一个静态字符串变量initDir 来保存服务器线程运行时所在的工作目录。服务器的初始工作目录是由程序运行时用户输入的,缺省为C盘的根目录。 具体的代码如下: public class ftpServer extends Thread{ private Socket socketClient; private int counter; private static String initDir; public static void main(String[] args){ if(args.length != 0) { initDir = args[0]; }else{ initDir = "c:";} int i = 1; try{ System.out.println("ftp server started!"); //监听21号端口 ServerSocket s = new ServerSocket(21); for(;;){ //接受客户端请求 Socket incoming = s.accept(); //创建服务线程 new ftpServer(incoming,i).start(); i++; } }catch(Exception e){} } 2. 线程类的设计 线程类的主要设计都是在run()方法中实现。用run()方法得到客户端的套接字信息,根据套接字得到输入流和输出流,向客户端发送欢迎信息。 3. FTP 命令的处理 (1) 访问控制命令 ◆ user name(user) 和 password (pass) 命令处理代码如下: if(str.startsWith("USER")){ user = str.substring(4); user = user.trim(); out.println("331 Password");} if(str.startsWith("PASS")) out.println("230 User "+user+" logged in."); User 命令和 Password 命令分别用来提交客户端用户输入的用户名和口令。 ◆ CWD (CHANGE WORKING DIRECTORY) 命令处理代码如下: if(str.startsWith("CWD")){ String str1 = str.substring(3); dir = dir+"/"+str1.trim(); out.println("250 CWD command succesful"); } 该命令改变工作目录到用户指定的目录。 ◆ CDUP (CHANGE TO PARENT DIRECTORY) 命令处理代码如下: if(str.startsWith("CDUP")){ int n = dir.lastIndexOf("/"); dir = dir.substring(0,n); out.println("250 CWD command succesful"); } 该命令改变当前目录为上一层目录。 ◆ QUIT命令处理代码如下: if(str.startsWith("QUIT")) { out.println("GOOD BYE"); done = true; } 该命令退出及关闭与服务器的连接,输出GOOD BYE。 (2) 传输参数命令 ◆ Port命令处理代码如下: if(str.startsWith("PORT")) { out.println("200 PORT command successful"); int i = str.length() - 1; int j = str.lastIndexOf(","); int k = str.lastIndexOf(",",j-1); String str1,str2; str1=""; str2=""; for(int l=k+1;l<j;l++){ str1 = str2 + str.charAt(l); } for(int l=j+1;l<=i;l++){ str2 = str2 + str.charAt(l); } tempPort = Integer.parseInt(str1) * 16 *16 +Integer.parseInt(str2); } 使用该命令时,客户端必须发送客户端用于接收数据的32位IP 地址和16位 的TCP 端口号。这些信息以8位为一组,使用十进制传输,中间用逗号隔开。 ◆ TYPE命令处理代码如下: if(str.startsWith("TYPE")){ out.println("200 type set"); } TYPE 命令用来完成类型设置。 (3) FTP 服务命令 ◆ RETR (RETEIEVE) 和 STORE (STORE)命令处理的代码 if(str.startsWith("RETR")){ out.println("150 Binary data connection"); str = str.substring(4); str = str.trim(); RandomAccessFile outFile = new RandomAccessFile(dir+"/"+str,"r"); Socket tempSocket = new Socket(host,tempPort); OutputStream outSocket = tempSocket.getOutputStream(); byte byteBuffer[]= new byte[1024]; int amount; try{ while((amount = outFile.read(byteBuffer)) != -1){ outSocket.write(byteBuffer, 0, amount); } outSocket.close(); out.println("226 transfer complete"); outFile.close(); tempSocket.close(); } catch(IOException e){} } if(str.startsWith("STOR")){ out.println("150 Binary data connection"); str = str.substring(4); str = str.trim(); RandomAccessFile inFile = new RandomAccessFile(dir+"/"+str,"rw"); Socket tempSocket = new Socket(host,tempPort); InputStream inSocket = tempSocket.getInputStream(); byte byteBuffer[] = new byte[1024]; int amount; try{ while((amount =inSocket.read(byteBuffer) )!= -1){ inFile.write(byteBuffer, 0, amount); } inSocket.close(); out.println("226 transfer complete"); inFile.close(); tempSocket.close(); } catch(IOException e){} } 文件传输命令包括从服务器中获得文件RETR和向服务器中发送文件STOR,这两个命令的处理非常类似。处理RETR命令时,首先得到用户要获得的文件的名称,根据名称创建一个文件输入流,然后和客户端建立临时套接字连接,并得到一个输出流。随后,将文件输入流中的数据读出并借助于套接字输出流发送到客户端,传输完毕以后,关闭流和临时套接字。 STOR 命令的处理也是同样的过程,只是方向正好相反。 ◆ DELE (DELETE)命令处理代码如下: if(str.startsWith("DELE")){ str = str.substring(4); str = str.trim(); File file = new File(dir,str); boolean del = file.delete(); out.println("250 delete command successful"); } DELE 命令用于删除服务器上的指定文件。 ◆ LIST命令处理代码如下: if(str.startsWith("LIST")) { try{ out.println("150 ASCII data"); Socket tempSocket = new Socket(host,tempPort); PrintWriter out2= new PrintWriter(tempSocket.getOutputStream(),true); File file = new File(dir); String[] dirStructure = new String[10]; dirStructure= file.list(); String strType=""; for(int i=0;i<dirStructure.length;i++){ if( dirStructure[i].indexOf(".") == -1) { strType = "d ";} else {strType = "- ";} out2.println(strType+dirStructure[i]); } tempSocket.close(); out.println("226 transfer complete"); } catch(IOException e){} LIST 命令用于向客户端返回服务器中工作目录下的目录结构,包括文件和目录的列表。处理这个命令时,先创建一个临时的套接字向客户端发送目录信息。这个套接字的目的端口号缺省为1,然后为当前工作目录创建File 对象,利用该对象的list()方法得到一个包含该目录下所有文件和子目录名称的字符串数组,然后根据名称中是否含有文件名中特有的“.”来区别目录和文件。最后,将得到的名称数组通过临时套接字发送到客户端。 (责任编辑 Sunny) 
    原作者: 谷和启 
    原出处: 赛迪网
      

  2.   

    自己看吧,有好消息告诉我呀:在JAVA应用程序中如何实现FTP的功能关于sun.net.ftp.FTPClient类
    文章摘自http://netspring.myrice.com/program/java/technic/022.htm在JAVA的编程中,您也许会遇到FTP方面的编程,本文就来演示如何实现它。 
    以下是这三部分的JAVA源程序。 1)显示FTP服务器上的文件 void ftpList_actionPerformed(ActionEvent e) {
     String server=serverEdit.getText();//输入的FTP服务器的IP地址
        String user=userEdit.getText();    file://登录FTP服务器的用户名
        String password=passwordEdit.getText();//登录FTP服务器的用户名的口令
        String path=pathEdit.getText();//FTP服务器上的路径
        try {
        FtpClient ftpClient=new FtpClient();//创建FtpClient对象
        ftpClient.openServer(server);//连接FTP服务器
        ftpClient.login(user, password);//登录FTP服务器
           if (path.length()!=0) ftpClient.cd(path);
        TelnetInputStream is=ftpClient.list();
        int c;
        while ((c=is.read())!=-1) {
      System.out.print((char) c);}
                    is.close();
                    ftpClient.closeServer();//退出FTP服务器
             } catch (IOException ex) {;}
      }2)从FTP服务器上下传一个文件 void getButton_actionPerformed(ActionEvent e) {
     String server=serverEdit.getText();
        String user=userEdit.getText();
        String password=passwordEdit.getText();
        String path=pathEdit.getText();
        String filename=filenameEdit.getText();
       try {
        FtpClient ftpClient=new FtpClient();
        ftpClient.openServer(server);
        ftpClient.login(user, password);
           if (path.length()!=0) ftpClient.cd(path);
        ftpClient.binary();
        TelnetInputStream is=ftpClient.get(filename);
        File file_out=new File(filename);
           FileOutputStream os=new 
           FileOutputStream(file_out);
           byte[] bytes=new byte[1024];
        int c;
        while ((c=is.read(bytes))!=-1) {
           os.write(bytes,0,c);
        }
           is.close();
           os.close();
           ftpClient.closeServer();
        } catch (IOException ex) {;}
      }
    3)向FTP服务器上上传一个文件
     void putButton_actionPerformed(ActionEvent e) {
     String server=serverEdit.getText();
        String user=userEdit.getText();
        String password=passwordEdit.getText();
        String path=pathEdit.getText();
        String filename=filenameEdit.getText();
       try {
        FtpClient ftpClient=new FtpClient();
        ftpClient.openServer(server);
        ftpClient.login(user, password);
           if (path.length()!=0) ftpClient.cd(path);
        ftpClient.binary();
        TelnetOutputStream os=ftpClient.put(filename);
        File file_in=new File(filename);
           FileInputStream is=new FileInputStream(file_in);
           byte[] bytes=new byte[1024];
        int c;
        while ((c=is.read(bytes))!=-1){
     os.write(bytes,0,c);}
           is.close();
           os.close();
           ftpClient.closeServer();
        } catch (IOException ex) {;}
      }
    }
     
     
      

  3.   

    感谢楼上两位!
    不过服务器端的程序我基本已写完,只是和客户端联调时,不知如何处理用户名和密码,所以想有谁能提供一下可执行的ftp服务器端程序(含java源码).
      

  4.   

    看这里http://www.chinajavaworld.net/examples/applet/ftp/FtpApplet.html
      

  5.   

    if(strCommand.startsWith("USER")){
        strUser = strCommand.substring(4);
        strUser = strUser.trim();
        if(!strUser.equals("yourusername"){
           streamWriter.println("530 Not logged in.Undentified User Name.");       
           streamWriter.close();
           streamReader.close();
           socketClient.close();
        }
        streamWriter.println("331 Enter Password");
        strCommand = streamReader.readLine();
        if(strCommand.startsWith("PASS")){
           strPswd = strCommand.substring(4);
           strPswd = strPswd.trim();
           if(!strPswd.equals("yourpassword")){
              streamWriter.println("530 Not logged in.Unauthentic Password.");  
              streamWriter.close();
              streamReader.close(); 
              socketClient.close();         
           }     
           streamWriter.println("230 User " + strUser + " logged in."); 
         }
    }
      

  6.   

    有写好的服务器端、客户端程序给我发一个,mail是:[email protected]  小弟先谢啦