FTP_socket_java主要要点

来源:互联网 发布:深圳大数据研究院 编辑:程序博客网 时间:2024/05/22 17:58

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;    }}
原创粉丝点击