2013-09-04 13 views
8

私は、node.jsを使用してアクティブモードをサポートしているFilezillaに対してftpクライアントを書いています。私はftpとnode.jsの新人です。この練習をすることで、TCPソケット通信とftpプロトコルをよく理解できると思いました。また、node-ftpjsftpはアクティブモードをサポートしていないようですので、これはnpmに加えて(これはあまり使用されません)良いと思います。Node.js用のアクティブなFTPクライアント

私は、少なくとも時々は動作しますが、すべてではないコンセプトコードがあります。クライアントが動作する場合、クライアントはfile.txtというファイルをテキスト「hi」でアップロードします。 それが動作するとき、私はこれを取得:それは動作しない場合は、私はこの取得

220-FileZilla Server version 0.9.41 beta 
220-written by Tim Kosse ([email protected]) 
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 ([email protected]) 
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でリファクタリングよ、または私はそれにいくつかの他の方法を行う必要がありますか?

EDIT: ランダムポートを使用するようにserver.listenのコールバックを変更しました。これで私が以前に取得していた425が削除されました。しかし、私はまだファイル転送と一貫した動作を得ていません。

+0

これをチェックしましたか? https://github.com/sergi/jsftp。 – yeya

答えて

1

アクティブモードのFTP転送の流れはおおよそ次のようなものです。

  • 接続プリアンブル(USER/PASS
  • データ
  • はそのソケットのサーバーに通知するために、クライアントのローカルソケットを確立する(PORT
  • リモートファイルを書き込み用に開くようにサーバーに指示します(STOR
  • 上記の確立されたデータソケットからのデータ(socket.write()
  • は、作業が完了しているサーバー(QUIT)を知らせる
  • ファイル転送を終了する(socket.end())クライアント側からのストリームを閉じます
  • 開いているすべてのソケットとサーバーをクリーンアップします

    else if(sendFile){ 
        sendFile = false; 
    
        _send('STOR file.txt', function(){ 
    
        }); 
    } 
    

    サーバがで応答します。クライアントだから、

であなたは、このやった後、はあなたが確立したデータソケットに接続しており、データを受信する準備ができています。

この時点で実行の理由を簡単にするための1つの改善点は、事前定義されたboolではなく、解析された応答コードで動作するようにコントロールフローを変更することです。

function onData(chunk) { 
    console.log(chunk); 
    var code = chunk.substring(0,3); 

    if(code == '220'){ 

の代わり:

//ready for data 
else if (code == '150') { 
    dataSocket.write('some wonderful file contents\r\n', function(){}); 
    dataSocket.end(null, function(){}); 
} 

そしてクリーンアップするもう少し:

//transfer finished 
else if (code == '226') { 
    _send('QUIT', function(){ console.log("Saying Goodbye");}); 
} 

//session end 
else if (code == '221') { 
    cmdSocket.end(null, function(){}); 
    if(!!server){ server.close(); } 
} 

function onData(chunk) { 
    console.log(chunk.toString('binary')); 

    //if ftp server return code = 220 
    if(supplyUser){ 

次に、あなたがデータを送信するためのセクションを追加することができます明らかに物事はもっと複雑になるでしょう。複数のファイルなどがありますが、これにより、あなたの実証がより確実に実行されるはずです。

var net = require('net'); 
    Socket = net.Socket; 

var cmdSocket = new Socket(); 
cmdSocket.setEncoding('binary') 

var server = undefined; 
var dataSocket = undefined; 
var port = 21; 
var host = "localhost"; 
var user = "username"; 
var password = "password" 
var active = true; 

function onConnect(){ 
} 

var str=""; 
function onData(chunk) { 
    console.log(chunk.toString('binary')); 
    var code = chunk.substring(0,3); 
    //if ftp server return code = 220 
    if(code == '220'){ 
     _send('USER ' + user, function(){ 
     }); 
    }else if(code == '331'){ 
     _send('PASS ' + password, function(){ 
     }); 
    } 
    else if(code == '230'){ 
     if(active){ 
      server = net.createServer(function(socket){ 
       dataSocket = socket; 
       console.log('new connection'); 
       socket.setKeepAlive(true, 5000); 

       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; 

       _send('PORT 127,0,0,1,' + p1 + ',' + p2, function(){ 

       }); 
      }); 
     }else{ 
      _send('PASV', function(){ 

      }); 
     } 
    } 
    else if(code == '200'){ 
     _send('STOR file.txt', function(){ 

     }); 
    } 
    //ready for data 
    else if (code == '150') { 
    dataSocket.write('some wonderful file contents\r\n', function(){}); 
    dataSocket.end(null, function(){}); 
    } 

    //transfer finished 
    else if (code == '226') { 
    _send('QUIT', function(){ console.log("Saying Goodbye");}); 
    } 

    //session end 
    else if (code == '221') { 
    cmdSocket.end(null, function(){}); 
    if(!!server){ server.close(); } 
    } 
} 

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); 
} 
関連する問題