FTP_socket_java主要要点

FTP主要要点:
  1. 发送消息通过socket.getInputStream()/getOutputStream 的接口,比如发送USER数据

    java
    writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    writer.writer("USER "+user+"\r\n");

    注意\r\n,和USER后的空格

  2. ftp基于TCP的服务,使用2个端口,21->用于命令端口,20->用于数据端口但是数据端口并不总是20。这就是主动模式与被动模式的区别

  3. 主动FTP:客户端从非特定端口N向客户端21端口发送请求,客户端监听N+1 的端口,并发送“port N+1”到服务器,绑定自己的数据端口。

  4. N端口到FTP服务器21端口,客户端初始化

    1. 服务器21端口客户端N端口,服务器响应客户端
    2. 服务器20端口到客户机N+1端口,服务器初始数据到数据端口
    3. N+1端口到服务器20端口,客户端发送ACK到服务器数据端口
  5. 被动模式:在被动模式下,命令连接和数据连接都有客户端发起。服务端只响应客户端的请求即可。

    在被动模式下。客户端不会主动提交PORT命令来允许服务器回连它的数据端口,而是由服务器发送PORT P给客户端。

    xml
    227 Entering Passive Mode (127,0,0,1,212,237)

    这是进入PASV模式后的响应,127.0.0.1是本地主机,后面212,237是端口后,实际端口是212* 256 + 237 = 54509,这才是服务器分给我的数据端口后,每次上传,下载,获取服务文件列表,都需要通过这个端口,建立新的socket,获取数据。

    这样做的好处是避免服务器到客户端数据端口被防火墙过滤掉

    1. N端口到FTP服务器21端口,客户端初始化
    2. 服务器21端口客户端N端口,服务器响应客户端
    3. N+1端口到FTP服务器P(这里不是20端口了)端口,客户端初始化数据链路
    4. 服务器响应ACK给客户端
  6. 优缺点:主动模式对服务器有利,端口固定,对客户端来说,容易被客户端的防火墙柱塞数据端口。被动模式,对服务器不利,用到的高位数据端口可能被服务器的防火墙屏蔽。反正主动与否看数据端口是否由服务端发起,产生这个模式的锅防火墙背定了!

    本文章参考这篇文章

    http://jackiechen.blog.51cto.com/196075/193883

FTP数据传输:

  1. ftp的数据传输通过数据端口,进入被动模式,客户端主动连接数据端口,当通信端口21发送

    writeLine("LIST")后,在数据端口准备接受返回回来的数据,

    同理,上传和下载文件也是这么回事

  2. 其他的貌似我也没有研究了,反正作业要求就这么多,就到此位置了。

  3. 代码如下:

package ftpCient;

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.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.LinkedList;
import java.util.StringTokenizer;

//trylock /lock 是我在类外为了获取这个类的信息的锁,读者可以忽略。
public class SimpleFTP {

    Socket socket = null;
    BufferedReader reader = null;
    BufferedWriter writer = null;
    private static boolean DEBUG = false;

    LinkedList<String> strlist = new LinkedList<String>();

    boolean lock = false;

    public SimpleFTP() throws IOException, InterruptedException {
    }

    public synchronized void connect(String host) throws IOException, InterruptedException {
        connect(host, 21);
    }

    public synchronized void connect(String host, int port) throws IOException, InterruptedException {
        connect(host, port, "anonymous", "anonymous");
    }

    public synchronized void connect(String host, int port, String user, String pass)
            throws IOException, InterruptedException {
        if (socket != null) {
            throw new IOException("FTP is already connected!");
        }
        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 ")) {
            trylock();
            strlist.add("SimpleFTP received an unknown response when connecting to the FTP server: " + response);
            unlock();
        }

        sendLine("USER " + user);
        response = readLine();
        if (!response.startsWith("331 ")) {
            trylock();
            strlist.add("SimpleFTP received an unknown response after sending the user: " + response);
            unlock();
        }

        sendLine("PASS " + pass);
        response = readLine();
        if (!response.startsWith("230 ")) {
            trylock();
            strlist.add("SimpleFTP was unable to log in with the supplied password: " + response);
            unlock();
        }
        // now logged in
    }

    public synchronized void disconnect() throws IOException {
        try {
            sendLine("QUIT");
            readLine();
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            socket = null;
        }
    }

    public synchronized String pwd() throws IOException, InterruptedException {
        sendLine("PWD");
        String dir = null;
        Thread.sleep(100);
        String respone = readLine();
        if (respone.startsWith("257 ")) {
            int firstQuote = respone.indexOf('\"');
            int secondQuote = respone.indexOf('\"', firstQuote + 1);
            if (secondQuote > 0) {
                dir = respone.substring(firstQuote + 1, secondQuote);
            }
        }
        return dir;
    }

    public String list() throws IOException, InterruptedException {
        sendLine("PASV");
        String respone = readLine();
        sendLine("LIST");
        respone = readLine();
        String ip = null;
        int port = -1;
        int opening = respone.indexOf('(');
        int closing = respone.indexOf(')', opening + 1);
        if (closing > 0) {
            String dataLink = respone.substring(opening + 1, closing);
            StringTokenizer tokenizer = new StringTokenizer(dataLink, ",");
            try {
                ip = tokenizer.nextToken() + "." + tokenizer.nextToken() + "." + tokenizer.nextToken() + "."
                        + tokenizer.nextToken();
                port = Integer.parseInt(tokenizer.nextToken()) * 256 + Integer.parseInt(tokenizer.nextToken());
            } catch (Exception e) {
                trylock();
                strlist.add("data link information:" + respone);
                unlock();
            }

        }
        Socket dataSocket = new Socket(ip, port);
        respone = readLine();
        BufferedInputStream input = new BufferedInputStream(dataSocket.getInputStream());
        // maybe out limit ,but I just want easy
        byte[] buffer = new byte[10240];
        int byteRead = 0;
        byteRead = input.read(buffer);
        String string = new String(buffer, 0, byteRead);
        return string;
    }

    public synchronized boolean cwd(String dir) throws IOException, InterruptedException {
        sendLine("CMD " + dir);
        String respone = readLine();
        return (respone.startsWith("250 "));
    }

    public synchronized boolean stor(File file) throws IOException, InterruptedException {
        if (file.isDirectory()) {
            trylock();
            strlist.add("FTP canot upload dir");
            unlock();
        }
        String filename = file.getName();
        return stor(filename, filename);

    }

    public synchronized boolean stor(String uploadFilename, String filename) throws IOException, InterruptedException {
        BufferedInputStream input = new BufferedInputStream(new FileInputStream(uploadFilename));
        sendLine("PASV");
        String respone = readLine();
        if (!respone.startsWith("227 ")) {
            trylock();
            strlist.addLast("SimpleFTP could not request passive mode: " + respone);
            unlock();
        }
        String ip = null;
        int port = -1;
        int opening = respone.indexOf('(');
        int closing = respone.indexOf(')', opening + 1);
        if (closing > 0) {
            String dataLink = respone.substring(opening + 1, closing);
            StringTokenizer tokenizer = new StringTokenizer(dataLink, ",");
            ip = tokenizer.nextToken() + "." + tokenizer.nextToken() + "." + tokenizer.nextToken() + "."
                    + tokenizer.nextToken();
            port = Integer.parseInt(tokenizer.nextToken()) * 256 + Integer.parseInt(tokenizer.nextToken());
        }
        trylock();
        sendLine("STOR " + filename);
        Socket dataSocket = new Socket(ip, port);
        String response = readLine();
        unlock();
        if (!response.startsWith("125 ")) {
            if (!response.startsWith("150 ")) {
                trylock();
                strlist.add("SimpleFTP was not allowed to send the file: " + response);
                unlock();
            }
        }

        BufferedOutputStream outputStream = new BufferedOutputStream(dataSocket.getOutputStream());
        byte[] buffer = new byte[4096];
        int byteRead = 0;
        while ((byteRead = input.read(buffer)) != -1) {
            outputStream.write(buffer, 0, byteRead);

        }

        outputStream.flush();
        outputStream.close();
        input.close();
        return true;
    }

    public synchronized boolean pasv() throws IOException, InterruptedException {
        sendLine("PASV");
        return true;
    }

    public synchronized boolean bin() throws IOException, InterruptedException {
        sendLine("TYPE I");
        String response = readLine();
        return (response.startsWith("200 "));
    }

    public synchronized boolean ascii() throws IOException, InterruptedException {
        sendLine("TYPE A");
        String response = readLine();
        return (response.startsWith("200 "));
    }

    private void sendLine(String line) throws IOException {
        if (socket == null) {
            throw new IOException("FTP not connected");
        }
        try {
            writer.write(line + "\r\n");
            writer.flush();
            if (DEBUG)
                System.out.println(">" + line);
        } catch (IOException e) {
            socket = null;
            throw e;
        }

    }

    public String readLine() throws IOException, InterruptedException {
        String line = reader.readLine();
        trylock();
        strlist.add(line);
        System.out.println(line);
        unlock();
        return line;
    }

    public String[] getOutput() throws InterruptedException {
        if (strlist.isEmpty())
            return null;
        trylock();
        String[] tmp = new String[strlist.size()];
        for (int i = 0; i < strlist.size(); i++)
            tmp[i] = strlist.get(i);
        strlist.clear();
        unlock();
        return tmp;
    }

    private void trylock() throws InterruptedException {
        while (lock) {
            Thread.sleep(50);
        }
        lock = true;
    }

    private void unlock() {
        lock = false;
    }

    public boolean isLock() {
        return lock;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值