2011-05-10 19 views
7

मेरे पास दो नोड प्रक्रियाएं हैं जो एक-दूसरे से बात करती हैं। मैं उन्हें [नोड सर्वर] और [नोड प्रेषक] कहूंगा। [नोड प्रेषक] लगातार सूचनाओं को संसाधित करता है और [नोड सर्वर] पर एक टीसीपी कनेक्शन पर एक संदेश लिखता है। [नोड सर्वर] फिर एक स्टेटस संदेश वापस लिखता है।Node.js टीसीपी सर्वर आने वाले बफर

var message = "Test Message"; 
[Node Sender].connection.write(message); 

की [नोड सर्वर] उदाहरण::

[नोड भेजने वाले] का उदाहरण

[Node Server].socket.on("data", function(p_data) { 
    this.write("OK"); 

    // Do some work with p_data 
} 

यह समस्या के बिना काम करता है, p_data हमेशा होता है "परीक्षण संदेश" जब भेजा 5 मिलीसेकंड से ऊपर कुछ भी पर। हालांकि, अगर मैं [नोड प्रेषक] प्रत्येक मिलीसेकंड लिखने के लिए p_data कभी-कभी "टेस्ट संदेशटेस्ट संदेशटेस" जैसे कुछ के साथ समाप्त होता है।

मैं समझता हूं कि [नोड प्रेषक] में बफर शायद लिखने के आदेश से तेज़ी से भर रहा है। क्या असीमित शेष रहते हुए संदेशों को भेजने में एक-से-एक अनुपात को मजबूर करने का कोई तरीका है?

मैं निश्चित रूप से बस अपना संदेश के लिए एक टर्मिनेटर जोड़ सकते हैं और सिर्फ [नोड सर्वर] में एक बफर को भरने, लेकिन मुझे यकीन है कि वहाँ कुछ स्पष्ट मैं याद आ रही थी नहीं था बनाना चाहते थे।

उत्तर

10

नहीं, आप कुछ भी नहीं खो रहे हैं और हां, आपको अपने संदेशों में कुछ प्रकार का समापन जोड़ने की आवश्यकता है।

दो बुनियादी यहां समस्याएं हैं:

  1. TCP प्रोटोकॉल धारा उन्मुख है, नहीं संदेश आधारित; इसका कोई आंतरिक ज्ञान नहीं है कि "संदेश" क्या हो सकता है।

  2. Node.js शुद्ध पुस्तकालय द्वारा चलाई डेटा घटना इंगित करता है कि कुछ डेटा आ गया है लेकिन क्या संदेश शामिल हो सकता है की किसी भी विचार के बिना, यह संकेत मिलता है नहीं कर सकते हैं कि यह किसी भी विशिष्ट डेटा प्राप्त हुआ है।

तो नोड से तेज़ी से आपके संदेश भेजकर उन्हें संसाधित कर सकते हैं, सॉकेट आरईवी बफर कई "संदेशों" के साथ भरता है।

इस समस्या का एक विशिष्ट समाधान, लाइन समाप्ति जोड़ने के लिए है के रूप में लाइनों 32-34 पर https://github.com/baudehlo/Haraka/blob/master/connection.js में पाया जा सकता:

self.client.on('data', function (data) { 
    self.process_data(data); 
}); 

और लाइनों 110-134:

Connection.prototype.process_data = function (data) { 
    if (this.disconnected) { 
    logger.logwarn("data after disconnect from " + this.remote_ip); 
    return; 
    } 

    this.current_data += data; 
    this._process_data(); 
}; 

Connection.prototype._process_data = function() { 
    var results; 
    while (results = line_regexp.exec(this.current_data)) { 
    var this_line = results[1]; 
    if (this.state === 'pause') { 
     this.early_talker = 1; 
     var self = this; 
     // If you talk early, we're going to give you a delay 
     setTimeout(function() { self._process_data() }, this.early_talker_delay); 
     break; 
    } 
    this.current_data = this.current_data.slice(this_line.length); 
    this.process_line(this_line); 
    } 
}; 
+0

जवाब और उदाहरण के लिए धन्यवाद। – user747454

7

अपना पूरा संदेश प्राप्त करने के लिए आपको आने वाले बफर डेटा को जमा करने की आवश्यकता है। कृपया नीचे उदाहरण देखें। यह सर्वर 4 बाइट हेडर और संदेश निकाय वाले डेटा की अपेक्षा करता है।हेडर हस्ताक्षरित int है जिसका अर्थ है शरीर की कुल लंबाई और शरीर डिलिमीटर '|' के साथ स्ट्रिंग डेटा है। कृपया ध्यान दें कि यह संभव है कि एक समय में यह 'हेडर और संदेश' प्राप्त नहीं हो रहा है। इसलिए हमें आने वाले डेटा को तब तक जमा करने की आवश्यकता है जब तक हमें डेटा की पूर्ण लंबाई न मिल जाए। और यह भी संभव है कि एक समय में एकाधिक 'हेडर और संदेश' प्राप्त हो रहा है। मुद्दा यह है कि हमें डेटा संचय की आवश्यकता है।

var SERVER_PORT = 8124; 
var TCP_DELIMITER = '|'; 
var packetHeaderLen = 4; // 32 bit integer --> 4 

var server = net.createServer(function(c) { 
    var accumulatingBuffer = new Buffer(0); 
    var totalPacketLen = -1; 
    var accumulatingLen = 0; 
    var recvedThisTimeLen= 0; 
    var remoteAddress = c.remoteAddress; 
    var address= c.address(); 
    var remotePort= c.remotePort; 
    var remoteIpPort = remoteAddress +":"+ remotePort; 

    console.log('-------------------------------'+remoteAddress); 
    console.log('remoteIpPort='+ remoteIpPort); 

    c.on('data', function(data) { 
     console.log('received data length :' + data.length); 
     console.log('data='+ data); 

     recvedThisTimeLen = data.length; 
     console.log('recvedThisTimeLen='+ recvedThisTimeLen); 

     //accumulate incoming data 
     var tmpBuffer = new Buffer(accumulatingLen + recvedThisTimeLen); 
     accumulatingBuffer.copy(tmpBuffer); 
     data.copy (tmpBuffer, accumulatingLen ); // offset for accumulating 
     accumulatingBuffer = tmpBuffer; 
     tmpBuffer = null; 
     accumulatingLen += recvedThisTimeLen ; 
     console.log('accumulatingBuffer = ' + accumulatingBuffer ); 
     console.log('accumulatingLen =' + accumulatingLen); 

     if(recvedThisTimeLen < packetHeaderLen) { 
      console.log('need to get more data(less than header-length received) -> wait..'); 
      return; 
     } else if(recvedThisTimeLen == packetHeaderLen) { 
      console.log('need to get more data(only header-info is available) -> wait..'); 
      return; 
     } else { 
      console.log('before-totalPacketLen=' + totalPacketLen); 
      //a packet info is available.. 
      if(totalPacketLen < 0) { 
       totalPacketLen = accumulatingBuffer.readUInt32BE(0) ; 
       console.log('totalPacketLen=' + totalPacketLen); 
      } 
     }  

     //while=> 
     //in case of the accumulatingBuffer has multiple 'header and message'. 
     while(accumulatingLen >= totalPacketLen + packetHeaderLen) { 
      console.log('accumulatingBuffer= ' + accumulatingBuffer); 

      var aPacketBufExceptHeader = new Buffer(totalPacketLen ); // a whole packet is available... 
      console.log('aPacketBufExceptHeader len= ' + aPacketBufExceptHeader.length); 
      accumulatingBuffer.copy(aPacketBufExceptHeader, 0, packetHeaderLen, accumulatingBuffer.length); // 

      //////////////////////////////////////////////////////////////////// 
      //process one packet data 
      var stringData = aPacketBufExceptHeader.toString(); 
      var usage = stringData.substring(0,stringData.indexOf(TCP_DELIMITER)); 
      console.log("usage: " + usage); 
      //call handler 
      (serverFunctions [usage])(c, remoteIpPort, stringData.substring(1+stringData.indexOf(TCP_DELIMITER))); 
      //////////////////////////////////////////////////////////////////// 

      //rebuild buffer 
      var newBufRebuild = new Buffer(accumulatingBuffer.length); 
      newBufRebuild.fill(); 
      accumulatingBuffer.copy(newBufRebuild, 0, totalPacketLen + packetHeaderLen, accumulatingBuffer.length ); 

      //init  
      accumulatingLen -= (totalPacketLen +4) ; 
      accumulatingBuffer = newBufRebuild; 
      newBufRebuild = null; 
      totalPacketLen = -1; 
      console.log('Init: accumulatingBuffer= ' + accumulatingBuffer); 
      console.log('  accumulatingLen = ' + accumulatingLen); 

      if(accumulatingLen <= packetHeaderLen) { 
       return; 
      } else { 
       totalPacketLen = accumulatingBuffer.readUInt32BE(0) ; 
       console.log('totalPacketLen=' + totalPacketLen); 
      }  
     } 
    }); 

    ... 
}); 

कृपया पूरे उदाहरण के लिए नीचे देखें।

https://github.com/jeremyko/nodeChatServer

आशा इस मदद करते हैं।

संबंधित मुद्दे