2016-06-26 13 views
1

Ich habe einen Server auf bestimmten Port lauscht und erwartet Befehle die folgende Art und Weise -NodeJS Socket-Programmierung - senden Datenlänge

ersten vier Bytes die Länge des Befehls enthalten sollte und Bytes verbleibenden enthält den eigentlichen Befehl. Beispiel:

Wenn der Befehl, den ich senden möchte, {cmd:"EL",ptno:1234} ist, sollten die ersten vier Bytes die Zahl 20 in Big-Endian-Notation enthalten, da die Befehlslänge 20 beträgt, da die Befehle im UTF-8-Format sind . Die verbleibenden Bytes, die ich sende, haben den Befehl in ihnen.

Ich möchte wissen, wie dies in NodeJs zu tun. Auch wenn der Server Daten zurücksendet, muss ich die ersten vier Bytes lesen und die Datenlänge bestimmen und den Socket-Eingangsstrom entsprechend lesen. Bitte helfen Sie.

Antwort

1

Ich habe habe eine lib, die genau das tut, was Sie brauchen: https://www.npmjs.com/package/node-easysocket (mit Ausnahme von 4 Bytes in Little Endian zu schreiben, aber es ist sehr einfach zu beheben)

über Ihre Frage, hier gehen wir:

Für eine Nachricht senden, ist viel leichter, als empfangen zu können, die Sie gerade Nachricht an einen ByteArray brauchen umwandeln und eine ganze Zahl (4 Byte Big Endian), die die Größe des ByteArray + 4 setzt:

var buffer = new Buffer("Hello World or a JSON String", "binary"); 

//create a buffer with +4 bytes 
var consolidatedBuffer = new Buffer(4 + buffer.length); 

//write at the beginning of the buffer, the total size 
consolidatedBuffer.writeInt32BE(buffer.length, 0); 

//Copy the message buffer to the consolidated buffer at position 4  (after the 4 bytes about the size) 
buffer.copy(consolidatedBuffer, 4); 

//Send the consolidated buffer 
socket.write(consolidatedBuffer, function(err) { 
    if (err) console.log(err) 
}); 

wenn Sie wollen lesen, es wird ein bisschen komplizierter zB, weil Sie die Möglichkeit haben, einen in Blöcken gespleißten Puffer zu lesen.

Beispiel: Mein Puffer haben 10 MB Größe, aber meine Netzwerkverbindung kann ~ 100 Bytes pro Sekunde übertragen, so dass der Server viele Daten erhält und Sie speichern müssen, bis sie die erforderliche Größe entsprechend der Länge abgeschlossen haben in den ersten 4 Bytes informiert.

Die Javascript, wenn eine Dynamik der Sprache, so kann ich eine Runtime-Eigenschaft die die Socket-Objekt erstellen, um die gesammelten Stücke zu speichern:

socket.on('data', function(data) { 
    console.log("server bytes in:"+data.length); 
    receive(socket,data); 
}); 


function receive(socket, data){ 
    //Create a chunk prop if it does not exist 
    if(!socket.chunk){ 
     socket.chunck = { 
      messageSize : 0, 
      buffer: new Buffer(0), 
      bufferStack: new Buffer(0) 
     }; 
    } 
    //store the incoming data 
    socket.chunck.bufferStack = Buffer.concat([socket.chunck.bufferStack, data]); 
    //this is to check if you have a second message incoming in the tail of the first 
    var reCheck = false; 
    do { 
     reCheck = false; 
     //if message size == 0 you got a new message so read the message size (first 4 bytes) 
     if (socket.chunck.messageSize == 0 && socket.chunck.bufferStack.length >= 4) { 
      socket.chunck.messageSize = socket.chunck.bufferStack.readInt32BE(0); 
     } 

     //After read the message size (!= 0) and the bufferstack is completed and/or the incoming data contains more data (the next message) 
     if (socket.chunck.messageSize != 0 && socket.chunck.bufferStack.length >= socket.chunck.messageSize + 4) { 
      var buffer = socket.chunck.bufferStack.slice(4, socket.chunck.messageSize + 4); 
      socket.chunck.messageSize = 0; 
      socket.chunck.bufferStack = socket.chunck.bufferStack.slice(buffer.length + 4); 
      onMessage(socket, buffer); 
      //if the stack contains more data after read the entire message, maybe you got a new message, so it will verify the next 4 bytes and so on... 
      reCheck = socket.chunck.bufferStack.length > 0; 
     } 
    } while (reCheck); 
} 

function onMessage(socket, buffer){ 
    console.log("message received from: "+socket+" with data:"+data.toString()+"); 
}