FTP

xiaoxiao2021-02-28  109

FTP主要要点:

发送消息通过socket.getInputStream()/getOutputStream 的接口,比如发送USER数据

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

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

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

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

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

服务器21端口客户端N端口,服务器响应客户端服务器20端口到客户机N+1端口,服务器初始数据到数据端口N+1端口到服务器20端口,客户端发送ACK到服务器数据端口

被动模式:在被动模式下,命令连接和数据连接都有客户端发起。服务端只响应客户端的请求即可。

在被动模式下。客户端不会主动提交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,获取数据。

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

N端口到FTP服务器21端口,客户端初始化服务器21端口客户端N端口,服务器响应客户端N+1端口到FTP服务器P(这里不是20端口了)端口,客户端初始化数据链路服务器响应ACK给客户端

优缺点:主动模式对服务器有利,端口固定,对客户端来说,容易被客户端的防火墙柱塞数据端口。被动模式,对服务器不利,用到的高位数据端口可能被服务器的防火墙屏蔽。反正主动与否看数据端口是否由服务端发起,产生这个模式的锅防火墙背定了!

本文章参考这篇文章

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

FTP数据传输:

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

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

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

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

代码如下:

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; } }
转载请注明原文地址: https://www.6miu.com/read-29415.html

最新回复(0)