public FTPCommunicationChannel(Socket connection, String charsetName)
throws IOException {
this.connection = connection;
this.charsetName = charsetName;
InputStream inStream = connection.getInputStream();
OutputStream outStream = connection.getOutputStream();
// Wrap the streams into reader and writer objects.
reader = new NVTASCIIReader(inStream, charsetName);
writer = new NVTASCIIWriter(outStream, charsetName);
}
private String read() throws IOException {
// Read the line from the server.
String line = reader.readLine();
if (line == null) {
throw new IOException("FTPConnection closed");
}
// Call received() method on every communication listener
// registered.
for (Iterator iter = communicationListeners.iterator(); iter.hasNext();) {
FTPCommunicationListener l = (FTPCommunicationListener) iter.next();
l.received(line);
}
// Return the line read.
return line;
}
public void sendFTPCommand(String command) throws IOException {
writer.writeLine(command);
for (Iterator iter = communicationListeners.iterator(); iter.hasNext();) {
FTPCommunicationListener l = (FTPCommunicationListener) iter.next();
l.sent(command);
}
}
public String readLine() throws IOException {
StringBuffer buffer = new StringBuffer();
int previous = -1;
int current = -1;
while (true) {
int i = this.reader.read();
if (i == -1) {
if (buffer.length() == 0) {
return null;
}
return buffer.toString();
}
previous = current;
current = i;
if (/* previous == '\r' && */current == '\n') {
// End of line.
return buffer.toString();
} else if (previous == '\r' && current == 0) {
// Literal new line.
buffer.append(SYSTEM_LINE_SEPARATOR);
} else if (current != 0 && current != '\r') {
buffer.append((char) current);
}
}
}
该方法每次读取一行一旦遇到\n就返回。相反NVTASCIIReader 类发送信息也是如此:
public void writeLine(String str) throws IOException {
StringBuffer buffer = new StringBuffer();
boolean atLeastOne = false;
StringTokenizer st = new StringTokenizer(str, LINE_SEPARATOR);
int count = st.countTokens();
for (int i = 0; i < count; i++) {
String line = st.nextToken();
if (line.length() > 0) {
if (atLeastOne) {
buffer.append('\r');
buffer.append('\000');
}
buffer.append(line);
atLeastOne = true;
}
}
if (buffer.length() > 0) {
String statement = buffer.toString();
this.writer.write(statement);
this.writer.write("\r\n");
this.writer.flush();
}
}
6.
FTPFile[] list = ftp.list();这里是重点,主要是获取服务器当前目录的文件。该方法去除了很多判断的枝末^0^,如果想要完整地看它是如何处理的就要去研究查看源码,也不难就是变量多了点。这里使用被动方式,这个方式在文章开头理论就有说明。很简单,先在控制通道(比如A通道)发送一个PASV这个协议(说:hey,man 我想建立socket来传输数据,给个端口我),服务器返回一个随机端口告诉客户端,客户端分析出这个端口,然后与服务器建立一个新的socket。
private FTPDataTransferConnectionProvider openPassiveDataTransferChannel()
throws IOException, FTPIllegalReplyException, FTPException {
// Send the PASV command.
communication.sendFTPCommand("PASV");
// Read the reply.
FTPReply r = communication.readFTPReply();
touchAutoNoopTimer();
if (!r.isSuccessCode()) {
throw new FTPException(r);
}
// Use a regexp to extract the remote address and port.
String addressAndPort = null;
String[] messages = r.getMessages();
for (int i = 0; i < messages.length; i++) {
Matcher m = PASV_PATTERN.matcher(messages);
if (m.find()) {
int start = m.start();
int end = m.end();
addressAndPort = messages.substring(start, end);
break;
}
}
if (addressAndPort == null) {
// The remote server has not sent the coordinates for the
// data transfer connection.
throw new FTPIllegalReplyException();
}
// Parse the string extracted from the reply.
StringTokenizer st = new StringTokenizer(addressAndPort, ",");
int b1 = Integer.parseInt(st.nextToken());
int b2 = Integer.parseInt(st.nextToken());
int b3 = Integer.parseInt(st.nextToken());
int b4 = Integer.parseInt(st.nextToken());
int p1 = Integer.parseInt(st.nextToken());
int p2 = Integer.parseInt(st.nextToken());
final InetAddress remoteAddress;
// Ignore address?
// String useSuggestedAddress = System
// .getProperty(FTPKeys.PASSIVE_DT_USE_SUGGESTED_ADDRESS);
String useSuggestedAddress = "IP";
if ("true".equalsIgnoreCase(useSuggestedAddress)
|| "yes".equalsIgnoreCase(useSuggestedAddress)
|| "1".equals(useSuggestedAddress)) {
remoteAddress = InetAddress.getByAddress(new byte[] { (byte) b1,
(byte) b2, (byte) b3, (byte) b4 });
} else {
remoteAddress = InetAddress.getByName(host);
}
final int remotePort = (p1 << 8) | p2;
FTPDataTransferConnectionProvider provider = new FTPDataTransferConnectionProvider() {
public Socket openDataTransferConnection() {
// Establish the connection.
Socket dtConnection = null;
String remoteHost = remoteAddress.getHostAddress();
try {
dtConnection = connector.connectForDataTransferChannel(
remoteHost, remotePort);
} catch (IOException e) {
}
return dtConnection;
}
public void dispose() {
// nothing to do
}
};
return provider;
}