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


//本程序基于nonblock\EchoServer.java进行修改,添加了文件传输模块. 
 
package ftp; 
 
import java.io.*; 
import java.nio.*; 
import java.nio.channels.*; 
import java.nio.charset.*; 
import java.net.*; 
import java.util.*; 
 
public class EchoServerFTP{ 
  private Selector selector = null; 
  private ServerSocketChannel serverSocketChannel = null; 
  private int port = 8000; 
  private Charset charset=Charset.forName("GBK"); 
 
  public EchoServerFTP()throws IOException{ 
    selector = Selector.open(); 
    serverSocketChannel= ServerSocketChannel.open(); 
    serverSocketChannel.socket().setReuseAddress(true); 
    serverSocketChannel.configureBlocking(false); 
    serverSocketChannel.socket().bind(new InetSocketAddress(port)); 
    System.out.println("服务器启动"); 
  } 
 
  public void service() throws IOException{ 
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT ); 
    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.isAcceptable()) { 
              ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 
              SocketChannel socketChannel = (SocketChannel) ssc.accept(); 
              System.out.println("接收到客户连接,来自:" +socketChannel.socket().getInetAddress() + 
                                 ":" + socketChannel.socket().getPort()); 
              socketChannel.configureBlocking(false); 
              ByteBuffer buffer = ByteBuffer.allocate(1024); 
              socketChannel.register(selector, 
                                     SelectionKey.OP_READ | 
                                     SelectionKey.OP_WRITE, buffer); 
            } 
            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{ 
    ByteBuffer buffer=(ByteBuffer)key.attachment(); 
    SocketChannel socketChannel=(SocketChannel)key.channel(); 
    buffer.flip();  //把极限设为位置,把位置设为0 
    String data=decode(buffer); 
    if(data.indexOf("\r\n")==-1)return; 
    String outputData=data.substring(0,data.indexOf("\n")+1); 
    System.out.print(outputData); 
    ByteBuffer outputBuffer=encode("echo:"+outputData); 
    
    while(outputBuffer.hasRemaining()) 
      socketChannel.write(outputBuffer); 
 
    ByteBuffer temp=encode(outputData); 
    buffer.position(temp.limit()); 
    buffer.compact(); 
 
/*********************文件传输判定模块**************************/  
       if(outputData.startsWith("PUT")|outputData.startsWith("GET")){ 
         Thread fileThread=new Thread(new Handler(outputData)); 
          fileThread.start();  
      } 
/******************************************************/ 
 
    if(outputData.equals("bye\r\n")){ 
      key.cancel(); 
      socketChannel.close(); 
      System.out.println("关闭与客户的连接"); 
    } 
  } 
 
  public void receive(SelectionKey key)throws IOException{ 
    ByteBuffer buffer=(ByteBuffer)key.attachment(); 
 
    SocketChannel socketChannel=(SocketChannel)key.channel(); 
    ByteBuffer readBuff= ByteBuffer.allocate(32); 
    socketChannel.read(readBuff); 
    readBuff.flip(); 
 
    buffer.limit(buffer.capacity()); 
    buffer.put(readBuff); 
  } 
 
  public String decode(ByteBuffer buffer){  //解码 
    CharBuffer charBuffer= charset.decode(buffer); 
    return charBuffer.toString(); 
  } 
  public ByteBuffer encode(String str){  //编码 
    return charset.encode(str); 
  } 
 
  public static void main(String args[])throws Exception{ 
    EchoServerFTP server = new EchoServerFTP(); 
    server.service(); 
  } 
 
/************************内部类:文件传输模块*****************************************/ 
/**********************演示网络通道和文件通道对拷贝*****************************/ 
 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"))  
           fileReceive(msg.substring(4,msg.indexOf("\r\n"))); //提取文件名,并接收文件. 
       if (msg.startsWith("GET")) //接收文件 
          fileSend(msg.substring(4,msg.indexOf("\r\n"))); //提取文件名,并发送文件.       	 
      }catch(IOException e){ 
           e.printStackTrace(); 
   }finally{ 
      try{if(socketChannel!=null)socketChannel.close();}catch(IOException e){e.printStackTrace();} 
 }     
} 
   
public void fileSend(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 fileReceive(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("new"+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");     
} 
} 
}