我正在尝试编写一个针对 Filezilla 的 ftp 客户端,该客户端支持使用 node.js 的活动模式。我是 ftp 和 node.js 的新手。我想通过做这个练习我可以很好地理解 tcp socket 通信和 ftp 协议。另外,node-ftp和jsftp似乎不支持主动模式,所以我认为这将是对 npm 的一个很好的(虽然很少使用)补充。
我有一些至少有时有效的概念验证代码,但并非一直有效。在它工作的情况下,客户端上传一个名为file.txt
“hi”的文件。当它起作用时,我得到了这个:
220-FileZilla Server version 0.9.41 beta
220-written by Tim Kosse (Tim.Kosse@gmx.de)
220 Please visit http://sourceforge.net/projects/filezilla/
331 Password required for testuser
230 Logged on
listening
200 Port command successful
150 Opening data channel for file transfer.
server close
226 Transfer OK
half closed
closed
Process finished with exit code 0
当它不起作用时,我得到这个:
220-FileZilla Server version 0.9.41 beta
220-written by Tim Kosse (Tim.Kosse@gmx.de)
220 Please visit http://sourceforge.net/projects/filezilla/
331 Password required for testuser
230 Logged on
listening
200 Port command successful
150 Opening data channel for file transfer.
server close
half closed
closed
Process finished with exit code 0
所以,我没有得到 226,我不确定为什么会得到不一致的结果。
原谅写得不好的代码。一旦我确信我理解这应该如何工作,我将重构。:
var net = require('net'),
Socket = net.Socket;
var cmdSocket = new Socket();
cmdSocket.setEncoding('binary')
var server = undefined;
var port = 21;
var host = "localhost";
var user = "testuser";
var password = "Password1*"
var active = true;
var supplyUser = true;
var supplyPassword = true;
var supplyPassive = true;
var waitingForCommand = true;
var sendFile = true;
function onConnect(){
}
var str="";
function onData(chunk) {
console.log(chunk.toString('binary'));
//if ftp server return code = 220
if(supplyUser){
supplyUser = false;
_send('USER ' + user, function(){
});
}else if(supplyPassword){
supplyPassword = false;
_send('PASS ' + password, function(){
});
}
else if(supplyPassive){
supplyPassive = false;
if(active){
server = net.createServer(function(socket){
console.log('new connection');
socket.setKeepAlive(true, 5000);
socket.write('hi', function(){
console.log('write done');
})
socket.on('connect', function(){
console.log('socket connect');
});
socket.on('data', function(d){
console.log('socket data: ' + d);
});
socket.on('error', function(err){
console.log('socket error: ' + err);
});
socket.on('end', function() {
console.log('socket end');
});
socket.on('drain', function(){
console.log('socket drain');
});
socket.on('timeout', function(){
console.log('socket timeout');
});
socket.on('close', function(){
console.log('socket close');
});
});
server.on('error', function(e){
console.log(e);
});
server.on('close', function(){
console.log('server close');
});
server.listen(function(){
console.log('listening');
var address = server.address();
var port = address.port;
var p1 = Math.floor(port/256);
var p2 = port % 256;
_sendCommand('PORT 127,0,0,1,' + p1 + ',' + p2, function(){
});
});
}else{
_send('PASV', function(){
});
}
}
else if(sendFile){
sendFile = false;
_send('STOR file.txt', function(){
});
}
else if(waitingForCommand){
waitingForCommand = false;
cmdSocket.end(null, function(){
});
if(server)server.close(function(){});
}
}
function onEnd() {
console.log('half closed');
}
function onClose(){
console.log('closed');
}
cmdSocket.once('connect', onConnect);
cmdSocket.on('data', onData);
cmdSocket.on('end', onEnd);
cmdSocket.on('close', onClose);
cmdSocket.connect(port, host);
function _send(cmd, callback){
cmdSocket.write(cmd + '\r\n', 'binary', callback);
}
另外,是否server
合适,或者我应该以其他方式进行吗?
编辑:我将 server.listen 中的回调更改为使用随机端口。这已经删除了我之前得到的 425。但是,我仍然没有获得与文件传输一致的行为。