【问题标题】:node.js write filestream disordered in p2p file downloadnode.js在p2p文件下载中写入文件流无序
【发布时间】:2014-05-31 13:05:42
【问题描述】:

伙计们。我尝试使用 node.js 创建一个 p2p 文件共享应用程序。下载文件时,会逐块下载文件。

以下代码中使用的块大小为 1KB。但是它有一个问题,当可用套接字数MAX_SOCKET_CNT设置为30时,它就不起作用了。

如何运行代码:

首先运行node server.js,然后运行node client.js,这会将名为fav.mp3的文件下载到fav-local.mp3

下载后,尝试运行diff fav.mp3 fav-local.mp3检查文件是否下载完成。

您能帮我找出问题所在吗?

欢迎任何答案或建议。提前致谢。

这里是源代码:

server.js

var http = require("http");
var url = require("url");
var fs = require('fs');

function downloadBlock(request, response){
  var urlParts = url.parse(request.url, true);
  var query = urlParts.query;

  if('block_id' in query){
      response.writeHead(200, {"Content-Type": "audio/mpeg"});
      var startHere=parseInt(query["block_id"]);
      var BLOCK_SIZE=1024;
      var currentPosition=startHere*BLOCK_SIZE;
      var readStream = fs.createReadStream('fav.mp3',{start: startHere*BLOCK_SIZE, end:startHere*BLOCK_SIZE+BLOCK_SIZE-1});
      readStream.pipe(response);
  }else{
      response.writeHead(200, {"Content-Type": "text/html"});
      response.write("refused");
      response.end();
      console.log("Warning: not a file block download request...");
  }
}


http.createServer(downloadBlock).listen(8801);
console.log("Server has started. please ensure that the fav.mp3 file(size=439355B) is here.");

client.js

var http = require('http');
var fs = require('fs');

var remoteFile='fav.mp3';
var fileSize=439355;
var localFile='fav-local.mp3';
var totalBlocks=Math.floor((fileSize+1023)/1024);
/**************************************************/
//KEY POINT
var MAX_SOCKET_CNT=totalBlocks; //worked
//var MAX_SOCKET_CNT=30;//not work //????because of  recursive  downloadBlock function????
/*************************************************/
for(var i=0;i<MAX_SOCKET_CNT;++i){
        downloadBlock('127.0.0.1',8801,remoteFile, localFile,i,totalBlocks);
}

function downloadBlock(IP,PORT,remoteFile,localFile,blockID,totalBlocksNum){
        if(blockID >= totalBlocksNum) return;
        var BLOCK_SIZE=1024;
        var file = fs.createWriteStream(localFile,{start: blockID*BLOCK_SIZE});
        var request = http.get("http://localhost:"+PORT+"/download_block?block_id="+blockID, function(response) {
          response.pipe(file);
          file.on('finish', function() {
                var callback=function downloadBlockOver(){
                        console.log("compelete download blockID:"+blockID);
                        var nextBlockID=blockID+MAX_SOCKET_CNT;
                        if(nextBlockID<totalBlocksNum){
                                downloadBlock(IP,PORT,remoteFile,localFile,nextBlockID,totalBlocksNum); //why not this work if MAX_SOCKET_CNT=30???    
                        }
                }
                file.close(callback);
           });
        });
}

【问题讨论】:

    标签: javascript node.js download filestream p2p


    【解决方案1】:

    啊哈。 最后,我找到了解决方案。您必须先创建文件。然后在下载前用“r+”更改写流的标志。

    function touchFile(fileName,fileSize){
        var BLOCK_SIZE=1024;
        var totalBlocks=Math.floor((fileSize+BLOCK_SIZE-1)/BLOCK_SIZE);
        var file = fs.createWriteStream(fileName);
        var blockBuffer=new Buffer(BLOCK_SIZE);
        for(var i=0;i<totalBlocks-1;++i){
                file.write(blockBuffer,0, BLOCK_SIZE);
        }
        var leftToFill=new Buffer(fileSize-(totalBlocks-1)*BLOCK_SIZE);
        file.write(leftToFill,0, leftToFill.Length);
        file.end();
    }
    

    添加函数“touchFile(localFile,fileSize);”在下载块之前。 然后改变:

    var file = fs.createWriteStream(localFile,{start: blockID*BLOCK_SIZE});
    

    var file = fs.createWriteStream(localFile,{start: blockID*BLOCK_SIZE,flags:'r+',autoClose: true});
    

    现在可以使用了。

    【讨论】:

      【解决方案2】:

      touchFile 仅在 MAX_SOCKET_CNT==3 时起作用。 最终的解决方案是使用节点模块random-access-filehttps://github.com/mafintosh/random-access-file

      client.js 代码:

      var http = require('http');
      var fs = require('fs');
      var randomAccessFile = require('random-access-file');
      
      
      var remoteFile='fav.mp3';
      var fileSize=439355;
      //var fileSize=6000;//363213; //439355;
      var localFile='fav-local.mp3';
      var totalBlocks=Math.floor((fileSize+1023)/1024);
      /**************************************************/
      //KEY POINT
      //var MAX_SOCKET_CNT=totalBlocks; //worked
      var MAX_SOCKET_CNT=20;//worked
      /*************************************************/
      
      var file = randomAccessFile('fav-local.mp3');
      for(var i=0;i<MAX_SOCKET_CNT;++i){
          downloadBlock('127.0.0.1',8801,remoteFile, localFile,i,totalBlocks);
      }
      file.close();
      
      function downloadBlock(IP,PORT,remoteFile,localFile,blockID,totalBlocksNum){
          if(blockID >= totalBlocksNum) return;
          var BLOCK_SIZE=1024;
          var chunks=[];
          var request = http.get("http://localhost:"+PORT+"/download_block?block_id="+blockID, function(response) {
            response.on('data', function (chunk) {
              chunks.push(chunk);
            });
            response.on('error', function (e) { 
              console.log('error.......'+e);
            });
            response.on('close', function () { 
              console.log('close ....');
            });
            response.on('end', function () { 
              var dataToProcess=Buffer.concat(chunks);
              console.log('block data size: ' + dataToProcess.length);
              file.write(blockID*BLOCK_SIZE, dataToProcess,
                          function(err) {
                                  if(err){
                                          console.log("error in write...");
                                  }else{
                                      var nextBlockID=blockID+MAX_SOCKET_CNT;
                                      if(nextBlockID<totalBlocksNum){
                                              console.log("download next block:"+nextBlockID);
                                              downloadBlock(IP,PORT,remoteFile,localFile,nextBlockID,totalBlocksNum);   
                                      }    
                      }
                          }
                    );
            });
          });
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-13
        • 2019-08-17
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 1970-01-01
        • 2016-05-13
        • 1970-01-01
        相关资源
        最近更新 更多