node.jsを使用してアクティブモードをサポートするFilezillaに対してftpクライアントを作成しようとしています。私はftpとnode.jsが初めてです。この演習を行うことで、tcp ソケット通信と 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 が削除されました。ただし、ファイル転送で一貫した動作が得られません。