www.pudn.com > javaFTP.rar > EchoClientFTP.java


//本程序基于nonblock\EchoClient.java进行修改,添加了文件传输模块. 
 
package ftp; 
 
import java.net.*; 
import java.io.*; 
import java.nio.channels.*; 
import java.nio.charset.*; 
import java.nio.*; 
import java.util.*; 
 
public class EchoClientFTP{ 
  private Selector selector; 
  private SocketChannel socketChannel = null; 
   
  private ByteBuffer sendBuffer=ByteBuffer.allocate(1024); 
  private ByteBuffer receiveBuffer=ByteBuffer.allocate(1024); 
   
  private Charset charset=Charset.forName("GBK"); 
   
  public EchoClientFTP()throws IOException{ 
    socketChannel = SocketChannel.open(); 
    InetAddress ia = InetAddress.getLocalHost(); 
    InetSocketAddress isa = new InetSocketAddress(ia,8000); 
    socketChannel.connect(isa); 
    socketChannel.configureBlocking(false); 
    System.out.println("与服务器的连接建立成功"); 
    selector=Selector.open(); 
  } 
  
 public static void main(String args[])throws IOException{ 
    final EchoClientFTP client=new EchoClientFTP(); 
     
    Thread receiver=new Thread(){ ////键盘录入单独启用一个匿名线程. 
      public void run(){ client.receiveFromUser();  } 
     }; 
     receiver.start(); 
 
    client.talk(); 
  } 
 
  public void receiveFromUser(){ //键盘录入模块. 
    try{ 
       
      BufferedReader localReader=new BufferedReader(new InputStreamReader(System.in)); 
      String msg=null; 
      while((msg=localReader.readLine())!=null){ 
          synchronized(sendBuffer){ 
             sendBuffer.put(encode(msg + "\r\n")); 
         } 
 
/*********************文件传输判定**************************/  
/**********命令行格式是: PUT xxx.xxx或GET xxx.xxx*******************/ 
 
       if(msg.startsWith("PUT")|msg.startsWith("GET")){ 
         Thread fileThread=new Thread(new Handler(msg)); 
          fileThread.start();  
          continue;        
        } 
/**************************************************************/ 
        if(msg.equals("bye")) 
        break; 
      } 
    }catch(IOException e){ 
       e.printStackTrace(); 
    } 
  } 
 
  public void talk()throws IOException { 
     socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); 
      
     while (selector.select() > 0 ){ 
       Set readyKeys = selector.selectedKeys(); 
       Iterator it = readyKeys.iterator(); 
       while (it.hasNext()){ 
         SelectionKey key=null; 
         try{ 
             key = (SelectionKey) it.next(); 
             it.remove(); 
 
             if (key.isReadable()) { 
                 receive(key); 
             } 
             if (key.isWritable()) { 
                 send(key); 
             } 
         }catch(IOException e){ 
            e.printStackTrace(); 
            try{ 
                if(key!=null){ 
                    key.cancel(); 
                    key.channel().close(); 
                } 
            }catch(Exception ex){e.printStackTrace();} 
         } 
      }//#while 
    }//#while 
  } 
 
  public void send(SelectionKey key)throws IOException{ 
    SocketChannel socketChannel=(SocketChannel)key.channel(); 
     
    synchronized(sendBuffer){ 
         sendBuffer.flip(); //把极限设为位置 
         socketChannel.write(sendBuffer); 
         sendBuffer.compact(); 
     } 
  } 
  
  public void receive(SelectionKey key)throws IOException{ 
    SocketChannel socketChannel=(SocketChannel)key.channel(); 
    socketChannel.read(receiveBuffer); 
    receiveBuffer.flip(); 
    String receiveData=decode(receiveBuffer); 
 
    if(receiveData.indexOf("\n")==-1)return; 
 
    String outputData=receiveData.substring(0,receiveData.indexOf("\n")+1); 
    System.out.print("Server says: "+outputData); 
    if(outputData.equals("bye\r\n")){ 
        key.cancel(); 
        socketChannel.close(); 
        System.out.println("关闭与服务器的连接"); 
        selector.close(); 
        System.exit(0); 
    } 
 
    ByteBuffer temp=encode(outputData); 
    receiveBuffer.position(temp.limit()); 
    receiveBuffer.compact(); 
  } 
 
  public String decode(ByteBuffer buffer){  //解码 
    CharBuffer charBuffer= charset.decode(buffer); 
    return charBuffer.toString(); 
  } 
  public ByteBuffer encode(String str){  //编码 
    return charset.encode(str); 
  } 
 
/************************内部类: 文件传输模块**************************************/ 
/**********************演示网络通道和文件通道对拷贝***********************/ 
 class Handler implements Runnable{ 
   String msg=null;	 
   private ServerSocketChannel serverSocketChannel=null; 
   private SocketChannel socketChannel=null; 
   
   public Handler(String msg){ this.msg=msg;}     
	 
  public void run(){ 
    try{    		 
       if(msg.startsWith("PUT"))  
           fileUpload(msg.substring(4));//提取文件名,并上传文件. 
       if (msg.startsWith("GET"))  
          fileDownload(msg.substring(4));  //提取文件名,并下载文件.     	 
      }catch(IOException e){ 
           e.printStackTrace(); 
   }finally{ 
      try{if(socketChannel!=null)socketChannel.close();}catch(IOException e){e.printStackTrace();} 
 }     
} 
   
public void fileUpload(String fileName)throws IOException {//上传文件,由文件发送方启动20号监听端口,接收方发起连接. 
   serverSocketChannel= ServerSocketChannel.open(); 
   serverSocketChannel.socket().setReuseAddress(true); 
   serverSocketChannel.socket().bind(new InetSocketAddress(20)); 
   
   System.out.println("FTP启动,进行数据传输!!!"); 
    
   SocketChannel socketChannel = serverSocketChannel.accept();    
   System.out.println("New File Send to " + socketChannel.socket().getInetAddress() + ":"+socketChannel.socket().getPort()); 
        
   FileChannel fileChannel=new FileInputStream(fileName).getChannel(); //打开文件,取得通道。 
   
  socketChannel.write(encode(new Long(fileChannel.size()).toString()+"\n"));//发送文件大小. 
    
   fileChannel.transferTo(0,fileChannel.size(),socketChannel); //发送文件正文。  
    
   fileChannel.close(); 
   socketChannel.close(); 
   serverSocketChannel.close();	 
   System.out.println("File is sent over");	  
} 
   
public void fileDownload(String fileName)throws IOException{//下载文件,接收方先发起连接. 
    socketChannel = SocketChannel.open(); 
    InetAddress ia = InetAddress.getLocalHost(); 
    InetSocketAddress isa = new InetSocketAddress(ia,20); 
    socketChannel.connect(isa); 
     
   System.out.println("New File From" + socketChannel.socket().getInetAddress() + ":" +socketChannel.socket().getPort()); 
             
   FileChannel fileChannel=new FileOutputStream("new2"+fileName).getChannel(); //新建输出文件,得到通道.     
 
   ByteBuffer temp=ByteBuffer.allocate(32); 
   socketChannel.read(temp); 
   temp.flip(); 
   String dataString=decode(temp); 
   Long fileSize=new Long(dataString.substring(0,dataString.indexOf("\n")));//得到文件大小. 
     
   fileChannel.transferFrom(socketChannel,0,fileSize);//接收文件正文。     
		 
   fileChannel.close(); 
   socketChannel.close(); 
   System.out.println("File receives over");     
} 
} 
}