📄 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");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -