java构建简单的ftp服务

服务端代码:

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');
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值