java socket 实现FTP客户端

FTP(File Transfer Protocol, 文件传输协议)是支持Internet文件传输的各种规则所组成的集合。

FTP工作原理:双方至少需要建立两个TCP连接,一个成为控制连接,用于传输FTP命令;另一个称为数据连接,用于传输文件数据。

通过Socket编写FTP客户端,首先要了解服务器的命令

命令

描述

ABOR

中断数据连接程序

ACCT <account>

系统特权帐号

ALLO <bytes>

为服务器上的文件存储器分配字节

APPE <filename>

添加文件到服务器同名文件

CDUP <dir path>

改变服务器上的父目录

CWD <dir path>

改变服务器上的工作目录

DELE <filename>

删除服务器上的指定文件

HELP <command>

返回指定命令信息

LIST <name>

如果是文件名列出文件信息,如果是目录则列出文件列表

MODE <mode>

传输模式(S=流模式,B=块模式,C=压缩模式)

MKD <directory>

在服务器上建立指定目录

NLST <directory>

列出指定目录内容

NOOP

无动作,除了来自服务器上的承认

PASS <password>

系统登录密码

PASV

请求服务器等待数据连接

PORT <address>

IP 地址和两字节的端口 ID

PWD

显示当前工作目录

QUIT

从 FTP 服务器上退出登录

REIN

重新初始化登录状态连接

REST <offset>

由特定偏移量重启文件传递

RETR <filename>

从服务器上找回(复制)文件

RMD <directory>

在服务器上删除指定目录

RNFR <old path>

对旧路径重命名

RNTO <new path>

对新路径重命名

SITE <params>

由服务器提供的站点特殊参数

SMNT <pathname>

挂载指定文件结构

STAT <directory>

在当前程序或目录上返回信息

STOR <filename>

储存(复制)文件到服务器上

STOU <filename>

储存文件到服务器名称上

STRU <type>

数据结构(F=文件,R=记录,P=页面)

SYST

返回服务器使用的操作系统

TYPE <data type>

数据类型(A=ASCII,E=EBCDIC,I=binary)

USER <username>>

系统登录的用户名

FTP 响应码:

响应代码

解释说明

110

新文件指示器上的重启标记

120

服务器准备就绪的时间(分钟数)

125

打开数据连接,开始传输

150

打开连接

200

成功

202

命令没有执行

211

系统状态回复

212

目录状态回复

213

文件状态回复

214

帮助信息回复

215

系统类型回复

220

服务就绪

221

退出网络

225

打开数据连接

226

结束数据连接

227

进入被动模式(IP 地址、ID 端口)

230

登录因特网

250

文件行为完成

257

路径名建立

331

要求密码

332

要求帐号

350

文件行为暂停

421

服务关闭

425

无法打开数据连接

426

结束连接

450

文件不可用

451

遇到本地错误

452

磁盘空间不足

500

无效命令

501

错误参数

502

命令没有执行

503

错误指令序列

504

无效命令参数

530

未登录网络

532

存储文件需要帐号

550

文件不可用

551

不知道的页类型

552

超过存储分配

553

文件名不允许


基本步骤:建立连接--->获取文件列表---->对文件进行操作


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.StringTokenizer;


/**
 * @description 没有图形用户界面, 只编写了连接,获取当前目录,上传文件功能。
 */
public class simpleFTP {

	private Socket socket = null;
	
	private BufferedReader reader = null;
	
	private BufferedWriter writer = null;
	
	private static boolean debug = false;
	
	private String user = "a";
	
	private String pass = "b";
	
	public simpleFTP() {
		
	}
	/**
	 * connect to the ftp server
	 * @param host
	 * @throws Exception
	 */
	public synchronized void connect(String host) throws Exception {
		connect(host, 21, user, pass);
	}
	
	public synchronized void connect(String host, int port, String user, String pass) throws Exception {
		if(socket != null) {
			throw new Exception("already connect!");
		}
		socket = new Socket(host, port);
		reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		String response = readLine();
		if(!response.startsWith("220")) {
			throw new Exception("unknow response after connect!");
		}
		sendLine("USER " + user);
		response = readLine();
		if(!response.startsWith("331")) {
			throw new Exception("unknow response after send user");
		}
		sendLine("PASS " + pass);
		response = readLine();
		if(!response.startsWith("230")) {
			throw new Exception("unknow response after send pass");
		}
		System.out.println("login!");
	}
	
	private void sendLine(String line) throws Exception {
		if(socket == null) {
			throw new Exception("not connect!");
		}
		writer.write(line + "\r\n");
		writer.flush();
		if(debug) {
			System.out.println(">" + line);
		}
	}
	
	private String readLine() throws IOException {
		String line = reader.readLine();
		if(debug) {
			System.out.println("<" + line);
		}
		return line;
	}
	
	/**
	 * get the working directory of the FTP server
	 * @return
	 * @throws Exception
	 */
	public synchronized String pwd() throws Exception {
		sendLine("PWD");
		String dir = null;
		String response = readLine();
		if(response.startsWith("257")) {
			int firstQuote = response.indexOf("/");
			int secondQuote = response.indexOf("/", firstQuote + 1);
			if(secondQuote > 0) {
				dir = response.substring(firstQuote + 1, secondQuote);
			}
		}
		return dir;
	}
	
	/**
	 * send a file to ftp server
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public synchronized boolean stor(File file) throws Exception {
		if(!file.isDirectory()) {
			throw new Exception("cannot upload a directory!");
		}
		String fileName = file.getName();
		return upload(new FileInputStream(file), fileName);
	}
	
	public synchronized boolean upload(InputStream inputStream, String fileName) throws Exception {
		BufferedInputStream input = new BufferedInputStream(inputStream);
		sendLine("PASV");
		String response = readLine();
		if(!response.startsWith("227")) {
			throw new Exception("not request passive mode!");
		}
		String ip = null;
		int port = -1;
		int opening = response.indexOf('(');
		int closing = response.indexOf(')', opening + 1);
		if(closing > 0) {
			String dataLink = response.substring(opening + 1, closing);
			StringTokenizer tokenzier = new StringTokenizer(dataLink, ",");
			try {
				ip = tokenzier.nextToken() + "." + tokenzier.nextToken() + "." 
						+  tokenzier.nextToken() + "." + tokenzier.nextToken();
				port = Integer.parseInt(tokenzier.nextToken()) * 256 +Integer.parseInt(tokenzier.nextToken());;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				throw new Exception("bad data link after upload!");
			}
		}
		sendLine("STOR " + fileName);
		Socket dataSocket = new Socket(ip, port);
		response = readLine();
		if(!response.startsWith("150")) {
			throw new Exception("not allowed to send the file!");
		}
		BufferedOutputStream output = new BufferedOutputStream(dataSocket.getOutputStream());
		byte[] buffer = new byte[4096];
		int bytesRead = 0;
		while((bytesRead = input.read(buffer)) != -1) {
			output.write(buffer, 0, bytesRead);
		}
		output.flush();
		output.close();
		input.close();
		response = readLine();
		return response.startsWith("226");
	}
	
	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		simpleFTP  ftp = new simpleFTP();
		ftp.connect("192.168.2.6");
	}

}



展开阅读全文

没有更多推荐了,返回首页