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