📄 ftp.java
字号:
import java.net.*;
import java.io.*;
public class Ftp {
//准备socket
Socket ctrlSocket; //控制用socket
public PrintWriter ctrlOutput; //控制输出的流
public BufferedReader ctrlInput;//控制输入的流
final int CTRLPORT = 21 ; //控制用端口
//openConnection方法
//由地址和端口 构造Socket 形成控制用的流
public void openConnection(String host)throws IOException,UnknownHostException
{
ctrlSocket = new Socket(host, CTRLPORT);//21
ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream());
ctrlInput = new BufferedReader(new InputStreamReader
(ctrlSocket.getInputStream()));
}
public void closeConnection()
throws IOException
{
ctrlSocket.close() ;
}
//showMenu 立法
//输出 FTP 的命令菜单
public void showMenu()
{
System.out.println("~~~~~~~~~~~~~~> 命令格式 <~~~~~~~~~~~~~~~") ;
System.out.print("1 dir ;") ;
System.out.print(" 2 cd ;") ;
System.out.print(" 3 pwd ;") ;
System.out.print(" 4 cdup ;") ;
System.out.print(" 5 mkd ;") ;
System.out.print(" 6 get ;") ;
System.out.println(" 7 put .") ;
System.out.println(" 8 asc .") ;
System.out.println(" 9 bin .") ;
System.out.println(" 10 abor .") ;
System.out.println(" 11 dele .") ;
System.out.println(" 12 quit .") ;
}
// getCommand方法
// 读用户指定的命令序号
public String getCommand()
{
String buf = "" ;
//从键盘输入
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
//while(buf.length() != 1){ // 循环接收一个字符的输入
try{
buf = lineread.readLine() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
//}
return (buf) ;
}
// doLogin方法
// 登陆FTP 服务器
public void doLogin()
{
String loginName = "" ;
String password = "" ;
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
try{
System.out.println("请输入用户名") ;
loginName = lineread.readLine() ;
ctrlOutput.println("USER " + loginName) ;
ctrlOutput.flush() ; //刷新流
System.out.println("请输入口令") ;
password = lineread.readLine() ;
ctrlOutput.println("PASS " + password) ;
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doQuit方法
// 向Ftp 注销
public void doQuit()
{
try{
ctrlOutput.println("QUIT ") ;// 发送 QUIT 命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doCd方法
// 切换目录
public void doCd()
{
String dirName = "" ;
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
try{
System.out.println("请输入目录名:") ;
dirName = lineread.readLine() ;
ctrlOutput.println("CWD " + dirName) ;// CWD命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
//doCdup
//上一层目录
public void doCdup()
{
try{
ctrlOutput.println("CDUP ") ;// CDUP命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
//显示当前目录
public void doPwd()
{
try{
ctrlOutput.println("PWD ") ;// PWD命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
//强行关闭当前的传送数据的Socket
public void doAbor()
{
try{
ctrlOutput.println("ABOR ") ;// ABOR命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
//删除服务器上的指定文件
public void doDele()
{
String dirName = "" ;
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
try{
System.out.println("请输入要删的文件名或目录名:") ;
dirName = lineread.readLine() ;
ctrlOutput.println("DELE " + dirName) ;// CWD命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
////建立目录
public void doMkd()
{
String dirName = "" ;
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
try{
System.out.println("请起个目录名:") ;
dirName = lineread.readLine() ;
ctrlOutput.println("MKD " + dirName) ;// CWD命令
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doLs方法
// 取得目录信息
public void doLs()
{
try{
int n ;
byte[] buff = new byte[1024] ;
// 建立数据连接
Socket dataSocket = dataConnection("LIST") ;
// 准备读取数据用流
BufferedInputStream dataInput
= new BufferedInputStream(dataSocket.getInputStream()) ;
// 读取目录信息
while((n = dataInput.read(buff)) > 0){
System.out.write(buff,0,n) ;
}
dataSocket.close() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// dataConnection方法
// 构造与服务器交换数据用的socket
// 再用 PORT 命令将端口号通知给服务器
public Socket dataConnection(String ctrlcmd)
{
String cmd = "PORT " ; //存贮发送PORT命令的数据 所用的变量
int i ;
Socket dataSocket = null ;
try{
// 取得自己用的地址
byte[] address = InetAddress.getLocalHost().getAddress() ;
// 用适当的端口号构造服务器 Socket
ServerSocket serverDataSocket = new ServerSocket(0,1) ;
// 准备传送port 命令用的数据
for(i = 0; i < 4; ++i)
cmd = cmd + (address[i] & 0xff) + "," ;
cmd = cmd + (((serverDataSocket.getLocalPort()) / 256) & 0xff)
+ ","
+ (serverDataSocket.getLocalPort() & 0xff) ;
// 利用控制用的流发送PORT命令
ctrlOutput.println(cmd) ;
ctrlOutput.flush() ;
// 向服务器发送处理对象命令(LIST,RETR及STOR)
ctrlOutput.println(ctrlcmd) ;
ctrlOutput.flush() ;
// 受理服务器的连接
dataSocket = serverDataSocket.accept() ;
serverDataSocket.close() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
return dataSocket ;
}
// doAscii方法
// 设置文本传输模式
public void doAscii()
{
try{
ctrlOutput.println("TYPE A") ;// A模式
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doBinary方法
// 设置二进制传输模式
public void doBinary()
{
try{
ctrlOutput.println("TYPE I") ;// I模式
ctrlOutput.flush() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doGet方法
// 取得服务器上的文件
public void doGet()
{
String fileName = "" ;
BufferedReader lineread
= new BufferedReader(new InputStreamReader(System.in)) ;
try{
int n ;
byte[] buff = new byte[1024] ;
// 指定报务器上文件的名
System.out.println("请输入文件名") ;
fileName = lineread.readLine() ;
// 在客户端上准备存储其内容的文件
FileOutputStream outfile = new FileOutputStream(fileName) ;
// 构造传输文件用的数据流
Socket dataSocket = dataConnection("RETR " + fileName) ;
BufferedInputStream dataInput
= new BufferedInputStream(dataSocket.getInputStream()) ;
// 从服务器上读取数据并存储到文件中
while((n = dataInput.read(buff)) > 0){
outfile.write(buff,0,n) ;
}
dataSocket.close() ;
outfile.close() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// doPut方法
// 向服务器发送文件
public void doPut()
{
String fileName = "" ;
BufferedReader lineread
= new BufferedReader(new InputStreamReader(System.in)) ;
try{
int n ;
byte[] buff = new byte[1024] ;
FileInputStream sendfile = null ;
// 指定文件名:
System.out.println("请输入文件名:") ;
fileName = lineread.readLine() ;
// 准备读出客户端的文件
try{
sendfile = new FileInputStream(fileName) ;
}catch(Exception e){
System.out.println("文件不存在") ;
return ;
}
// 准备发送数据用的流
Socket dataSocket = dataConnection("STOR " + fileName) ;
OutputStream outstr = dataSocket.getOutputStream() ;
// 读出文件,经由网络发送给服务器
while((n = sendfile.read(buff)) > 0){
outstr.write(buff,0,n) ;
}
dataSocket.close() ;
sendfile.close() ;
}catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
// execCommand方法
// 调用与命令对应的各种处理方法
public boolean execCommand(String command)
{
boolean cont = true ;
switch(Integer.parseInt(command)){
case 1 : // 显示服务器目录信息
doLs() ;
break ;
case 2 : // 切换服务器上的工作目录
doCd() ;
break ;
case 3 : // 显示当前目录
doPwd() ;
break ;
case 4: //上层目录
doCdup() ;
break ;
case 5 : // 新建目录
doMkd() ;
break ;
case 6 : // 从服务器上取得文件
doGet() ;
break ;
case 7 : // 向服务器发送文件
doPut() ;
break ;
case 8 : // 文件传输模式
doAscii() ;
break ;
case 9 : // 二进制模式
doBinary() ;
break ;
case 10 : // 强关dataSocket 流
doAbor() ;
break ;
case 11 : // 删除服务器上的指定文件
doDele() ;
break ;
case 12 : // 处理结束
doQuit() ;
cont = false ;
break ;
default : //其他的输入
System.out.println("请选择一个序号") ;
}
return(cont) ;
}
// main_proc方法
// 输出 Ftp 的命令菜单并进行各种处理
public void main_proc() throws IOException
{
boolean cont = true ;
try {
doLogin() ; // 进行登录
while(cont){
showMenu() ; // 输出菜单
cont = execCommand(getCommand()) ; //接收并执行命令
}
}
catch(Exception e){
System.err.print(e);
System.exit(1);
}
}
// getMsgs 立法
// 启动接收控制流的线程式
public void getMsgs(){
try {
CtrlListen listener = new CtrlListen(ctrlInput) ;
Thread listenerthread = new Thread(listener) ;
listenerthread.start() ;
}catch(Exception e){
e.printStackTrace() ;
System.exit(1) ;
}
}
// main方法
// 建立TCP连接,开始处理
public static void main(String[] arg){
try {
Ftp f = null;
if(arg.length < 1){
System.out.println("用法: java Ftp <host name>") ;
return ;
}
f = new Ftp();
f.openConnection(arg[0]); // 建立控制连接
f.getMsgs() ; //启动接收线程
f.main_proc(); // ftp 处理
f.closeConnection() ; // 关闭连接
System.exit(0) ; // 结束程序
}catch(Exception e){
e.printStackTrace();
System.exit(1);
}
}
}
// CtrlListen 类
class CtrlListen implements Runnable{
BufferedReader ctrlInput = null ;
// 构造器,指定读取地点
public CtrlListen(BufferedReader in){
ctrlInput = in ;
}
public void run(){
while(true){
try{ // 按行读入并写到标准输出上
System.out.println(ctrlInput.readLine()) ;
} catch (Exception e){
System.exit(1) ;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -