您的位置:首页 > 编程语言 > Java开发

java构建简单的ftp服务

2014-03-28 10:46 232 查看
服务端代码:

package examples.ftp;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

/**

* 模拟FTP服务器, 支持命令pwd,ls,get file

*

*/

public class FtpServer {

public static void main(String[] args) throws IOException {

FtpServer server = new FtpServer();

server.start();

}

public void start() throws IOException {

ServerSocket ss = new ServerSocket(9000);

while (true) {

Socket s = ss.accept();

new Agent(s).start();

}

}

class Agent extends Thread {

Socket s;

public Agent(Socket s) {

this.s = s;

}

public void run() {

try {

InputStream in = s.getInputStream();

OutputStream out = s.getOutputStream();

// 向客户端发协议, 先发生协议返回行,文本格式

IOUtils.println(out, "text,1");

// 发送消息内容,欢迎消息

IOUtils.println(out, "欢迎使用FTP演示服务!");

while (true) {

// 读取客户端发送到命令

String cmd = IOUtils.readLine(in).trim();

if ("pwd".equals(cmd)) {// 显示当前目录

pwd(out);

} else if ("ls".equals(cmd)) {

ls(out);

} else if (cmd.startsWith("get ")) {

get(cmd, out);

} else if ("bye".equalsIgnoreCase(cmd)) {

IOUtils.println(out, "text,1");

IOUtils.println(out, "Bye, Bye!");

s.close();

} else {

IOUtils.println(out, "text,1");

IOUtils.println(out, "只支持pwd,ls,get,bye!");

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

public void pwd(OutputStream out) throws IOException {

File dir = new File(".");

IOUtils.println(out, "text,1");

IOUtils.println(out, dir.getCanonicalPath());

}

public void ls(OutputStream out) throws IOException {

File dir = new File(".");

File[] files = dir.listFiles();

IOUtils.println(out, "text," + files.length);

for (File f : files) {

if (f.isDirectory()) {

IOUtils.println(out, "[" + f.getName() + "]");

} else {

IOUtils.println(out, f.getName());

}

}

}

public void get(String cmd, OutputStream out) throws IOException {

// cmd="get filename"

String name = cmd.split("\\s+")[1];

File file = new File(name);

if (!file.exists()) {

IOUtils.println(out, "text,1");

IOUtils.println(out, "没有文件!" + name);

return;

}

// 文件协议:

IOUtils.println(out, "file," + file.length() + "," + name);

FileInputStream in = new FileInputStream(file);

for (long i = 0; i < file.length(); i++) {

out.write(in.read());

}

out.flush();

in.close();

IOUtils.println(out, "text,2");

IOUtils.println(out, "发送成功:" + name);

IOUtils.println(out, "再见!");

}

}

客户端代码:

package examples.ftp;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.util.Scanner;

/**

* ftp 客户端可以使用命令 ls pwd get

*/

public class FtpClient {

public static void main(String[] args) throws IOException {

FtpClient client = new FtpClient();

client.open();

}

public void open() throws IOException {

Socket s = new Socket("localhost", 9000);

InputStream in = s.getInputStream();

OutputStream out = s.getOutputStream();

// 处理客户端对服务器的请求

new RequestProcess(out).start();

// 处理服务器的反馈信息

new ResponseProcess(in).start();

}

// 处理客户端对服务器的请求

class RequestProcess extends Thread {

OutputStream out;

public RequestProcess(OutputStream out) {

this.out = out;

}

public void run() {

try {

Scanner sc = new Scanner(System.in);

while (true) {

String s = sc.nextLine();// pwd ls get file

IOUtils.println(out, s);

if (s.equals("bye")) {

System.exit(0);

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ResponseProcess extends Thread {

InputStream in;

public ResponseProcess(InputStream in) {

this.in = in;

}

public void run() {

try {

while (true) {

String header = IOUtils.readLine(in);

if (header.startsWith("text,")) {

show(header, in);

} else if (header.startsWith("file,")) {

save(header, in);

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

public void show(String header, InputStream in) throws IOException {

int n = Integer.parseInt(header.split(",")[1]);

for (int i = 0; i < n; i++) {

String s = IOUtils.readLine(in);

System.out.println(s);

}

}

public void save(String header, InputStream in) throws IOException {

File dir = new File("ftp");

if (!dir.exists()) {

dir.mkdir();

}

// header: file,10,filename

String[] data = header.split(",");

long length = Long.parseLong(data[1]);

String filename = data[2];

File file = new File(dir, filename);

BufferedOutputStream out = new BufferedOutputStream(

new FileOutputStream(file));

for (long i = 0; i < length; i++) {

int b = in.read();

out.write(b);

}

out.close();

}

}

工具类:

package examples.ftp;

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileFilter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.OutputStream;

import java.io.RandomAccessFile;

import java.io.Serializable;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/** 文件的工具类 */

public class IOUtils {

/** 一次将文件读取到数组中 */

public static byte[] read(String file) throws IOException {

return read(new File(file));

}

public static byte[] read(File file) throws IOException {

// 按照文件大小 创建返回byte[]数组

byte[] buf = new byte[(int) file.length()];

// 用RAF只读打开文件

RandomAccessFile raf = new RandomAccessFile(file, "r");

// 使用 raf.read(byte[]) 读取全部内容

raf.read(buf);

// 关闭文件

raf.close();

return buf;

}

/** 复制文件, 复制in到out */

public static void cp(String in, String out) throws IOException {

cp(new File(in), new File(out));

}

public static void cp(File in, File out) throws IOException {

InputStream fin = new FileInputStream(in);// 可以使用File构�??

OutputStream fout = new FileOutputStream(out);

cp(fin, fout);

fin.close();

fout.close();// 关闭

}

/** 复制文件, 复制in到out, 不关闭流 */

public static void cp(InputStream in, OutputStream out) throws IOException {

byte[] buf = new byte[1024 * 512];// 512K缓冲

int count;

while ((count = in.read(buf)) != -1) {// 读取到buf

// System.out.println(count);//

out.write(buf, 0, count); // 写入到输出流

}

out.flush(); // 刷出缓冲到目标流

}

/** 不开缓冲 */

public static void cp2(InputStream in, OutputStream out) throws IOException {

int b;

while ((b = in.read()) != -1) { // 读取1个byte

out.write(b); // 写入到输出流

}

out.flush(); // 刷出缓冲到目标流

}

public static byte[] read(InputStream in) throws IOException {

byte[] buf = new byte[in.available()];

in.read(buf);

in.close();

return buf;

}

public static String toHexString(byte[] ary) {

if (ary == null || ary.length == 0)

return "";

StringBuilder buf = new StringBuilder();

if ((ary[0] & 0xff) <= 0xf) {

buf.append("0");

}

buf.append(Integer.toHexString(ary[0] & 0xff));

for (int i = 1; i < ary.length; i++) {

buf.append(",");

if ((ary[i] & 0xff) <= 0xf) {

buf.append("0");

}

buf.append(Integer.toHexString(ary[i] & 0xff));

}

return buf.toString();

}

public static String readHexString(String filename) throws IOException {

return toHexString(read(filename));

}

/**

* 将文件切分为 指定大小的系列文�? �?: IOUtiles.split("test.zip", 1024) 将文�? test.zip 切分�?

* 1024K(1M) 大小�? 系列文件 : test.zip.0, test.zip.1,...

*

* @param filename

* 源文件名

* @param size

* 文件大小, 以k为单�?

*/

public static void split(String file, int size) throws IOException {

if (size <= 0) {

throw new IllegalArgumentException("搞啥!");

}

int idx = 0;// 文件的序�?

InputStream in = new BufferedInputStream(new FileInputStream(file));

OutputStream out = new BufferedOutputStream(new FileOutputStream(file

+ "." + idx++));

int b;

int count = 0;

while ((b = in.read()) != -1) {

out.write(b);

count++;

if (count % (size * 1024) == 0) {

out.close();

out = new BufferedOutputStream(new FileOutputStream(file + "."

+ idx++));

}

}

in.close();

out.close();

}

/**

* 连接上面方法的系列文件为�?个文�? �?: IOUtiles.join("test.zip.0"); 在硬盘上生成�?个没有序号的文件:

* test.zip

*

* @param basename

* 第一个文�?, 如test.zip.0

*/

public static void join(String file) throws IOException {

String filename = file.substring(0, file.lastIndexOf("."));

String num = file.substring(file.lastIndexOf(".") + 1);

int idx = Integer.parseInt(num);

OutputStream out = new FileOutputStream(filename);

File f = new File(filename + "." + idx++);

while (f.exists()) {

InputStream in = new FileInputStream(f);

cp(in, out);

in.close();

f = new File(filename + "." + idx++);

}

out.close();

}

/**

* 将对象序列化到数组中 可以使用变长数组实现, 或�?�ByteArrayOutputStream实现

*

* @param obj

* �?个实现序列化接口的对�?

* @return 数组对象

* @throws IOException

*/

public static byte[] serialize(Serializable obj) throws IOException {

ByteArrayOutputStream os = new ByteArrayOutputStream();

ObjectOutputStream out = new ObjectOutputStream(os);

out.writeObject(obj);// 对象序列�?, foo

out.close();

byte[] ary = os.toByteArray();

return ary;

}

/**

* 反序列化byte数组 到对�?

*

* @param ary

* @return

* @throws IOException

* @throws ClassNotFoundException

*/

public static Object unserialize(byte[] data) throws IOException,

ClassNotFoundException {

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(

data));

Object o = in.readObject();// 反序列化

in.close();

return o;

}

/**

* 获取目录的全部文件

*

* @param dir

* @return

*/

public static List<File> listFile(File dir) {

File[] files = dir.listFiles(new FileFilter() {

public boolean accept(File pathname) {

return pathname.isFile();

}

});

return new ArrayList<File>(Arrays.asList(files));

}

/**

* 获取目录的全部文件, 指定扩展名的文件

*

* @param dir

* @return

*/

public static List<File> listFile(File dir, final String ext) {

File[] files = dir.listFiles(new FileFilter() {

public boolean accept(File pathname) {

return pathname.isFile() && pathname.getName().endsWith(ext);

}

});

return new ArrayList<File>(Arrays.asList(files));

}

/**

* 递归获取目录的全部文件

*

* @param dir

* @return

*/

public static List<File> listAll(File dir) {

List<File> all = listFile(dir);

File[] subs = dir.listFiles(new FileFilter() {

public boolean accept(File pathname) {

return pathname.isDirectory();

}

});

for (File sub : subs) {

all.addAll(listAll(sub));

}

return all;

}

/**

* 递归获取目录的全部文件, 指定扩展名的文件

*

* @param dir

* @return

*/

public static List<File> listAll(File dir, String ext) {

List<File> all = listFile(dir, ext);

File[] subs = dir.listFiles(new FileFilter() {

public boolean accept(File pathname) {

return pathname.isDirectory();

}

});

for (File sub : subs) {

all.addAll(listAll(sub, ext));

}

return all;

}

// 按行读取

public static String readLine(InputStream in) throws IOException {

ByteArrayOutputStream out = new ByteArrayOutputStream();

int b;

while (true) {

b = in.read();

if (b == '\n' || b == '\r' || b == -1) {// 编码是否是回车换行

break;

}

out.write(b);

}

return new String(out.toByteArray());

}

/**

* 从流中读取一行文件, 读取到一行的结束为止

*

* @param in

* @return

*/

public static String readLine(InputStream in, String charset)

throws IOException {

byte[] buf = {};

int b;

while (true) {

b = in.read();

if (b == '\n' || b == '\r' || b == -1) {// 编码是否是回车换行

break;

}

// buf = Arrays.copyOf(buf, buf.length + 1);

buf[buf.length - 1] = (byte) b;

}

if (buf.length == 0 && b == -1)

return null;

return new String(buf, charset);

}

/**

* 将text追加到文件filename的尾部,使用系统默认文本编码

*/

public static void println(String filename, String text) throws IOException {

println(new File(filename), text);

}

public static void println(File file, String text) throws IOException {

OutputStream out = new FileOutputStream(file, true);

println(out, text);

out.close();

}

/**

* 向流中输出一行字符串, 使用默认编码 不关闭流

*

* @param out

* 目标

* @param text

* 文本

* @throws IOException

*/

public static void println(OutputStream out, String text)

throws IOException {

out.write(text.getBytes());

out.write('\n');

out.flush();

}

/**

* 向流中输出一行字符串, 使用指定的编码 不关闭流

*

* @param out

* 目标

* @param text

* 文本

* @param charset

* 指定的编码

* @throws IOException

*/

public static void println(OutputStream out, String text, String charset)

throws IOException {

out.write(text.getBytes(charset));

out.write('\n');

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: