You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the client connects the server creates a small Buffer, writes two numbers at the beginning, and sends the buffer to the client.
Code
Server:
'use strict';constWebSocketServer=require('ws');constwss=newWebSocketServer.Server({maxPayload: Infinity,port: 3000});console.log('WAITING FOR CLIENT...\n');wss.on('connection',ws=>{// ANYTHING LESS 1024 DOESN'T WORK:constb=Buffer.alloc(9);// The first 9 + 1 Byte are used for a 64bit and an 8bit number, respectivelyb.writeDoubleLE(1,0);b.writeUInt8(255,8);console.log('SENDING BUFFER (length '+b.length+'):',b,'\n');ws.send(b);ws.onclose=({code, reason})=>{if(wss.clients.size===0){wss.close();}};});
Client
'use strict';constWebSocketServer=require('ws');constws=newWebSocketServer('ws://localhost:3000/ONE');ws.onmessage=message=>{if(message.datainstanceofBuffer){console.log('RECEIVED BUFFER\n');console.log('Buffer (length '+message.data.length+'): ',message.data);console.log('ArrayBuffer (length '+message.data.buffer.byteLength+'):',newUint8Array(message.data.buffer));// The first 8 bytes are for a Javascript numberconstcount=newDataView(message.data.buffer,0,8);console.log('\nNumber (Bytes 0..7):',count.getFloat64(0,true));constlastFragmentFlag=newDataView(message.data.buffer,8,1);console.log('Flag (Byte 8):',lastFragmentFlag.getUint8(0));ws.close(1000);}};
If the buffer sent by the server is less than 1024 Bytes the client receives garbage instead of the expected numbers - even though the dump of the buffer on the server side shows the correct buffer contents.
It all works as soon as I use at least 1024 for the allocated buffer size (sending a lot of unneeded zeros).
NOTE: The "1024" is not constant, that's the value I found works for this example. In my actual larger test code that does the full transfer the behavior is even more varied. I found when I use 64000 as the size it always works. The discrepancy in size between the Buffer and its ArrayBuffer (message.data.buffer) also is much larger there. Here it is just two bytes, in my stream test it's 9 vs. 57409, for example.
Also note that the exact same code for the transfers and for the log statement works find for my larger code test example where I do an actual transfer - only the last chunk, the one I modeled here, causes the problem. So my general approach with how I write those numbers into the buffer and how I get them back on the client works, apparently.
Is it possible the underlying ArrayBuffer is not zeroed? So when I have a smaller buffer than before I get in trouble?
Client code slightly changed for [µws](https://github.com/uNetworking/bindings/tree/master/nodejs), such as wss.clients.length instead of wss.clients.size, and I get an ArrayBuffer not a Buffer, it shows the expected result:
RECEIVED BUFFER
Buffer (length 9): ArrayBuffer { byteLength: 9 }
Number (Bytes 0..7): 1
Flag (Byte 8): 255
Browser as Client (works)
The problem is the client side - the example works fine when I use the browser (Google Chrome).
Start the server script in a console (same as before)
In Google Chrome go to http://localhost:3000/ (I also tried IE Edge and the same code below worked there too)
Open a console (F12) and paste and execute the code:
My use case - not really relevant but just for the background story: I send a binary stream over websocket and since the client may issue many different requests simultaneously each one gets an ID. Now I have to add that ID to each chunk of the binary stream . I do that by putting 9 Bytes in front of the actual chunk. It all works fine during the stream, when the buffers are large - but for some inexplicable reason the last message, supposed to signify the end (Byte 9 is the "end" flag, 0 during the stream, 255 for the last chunk) has both the numeric ID (Bytes 0...7) and the flag garbled. If I blow up the last chunk to be much larger than actually necessary it works.
The text was updated successfully, but these errors were encountered:
lll000111
changed the title
Sending buffers smaller than 1024 Bytes has unexpected (messy) result
Sending small buffers has unexpected (messy) result
Jul 20, 2017
lll000111
changed the title
Sending small buffers has unexpected (messy) result
Sending small buffers has unexpected result - the client receives the correct buffer but messes it up
Jul 20, 2017
I use node.js v8.2.0 and ws v3.0.0.
Below is a tiny server and client example.
When the client connects the server creates a small Buffer, writes two numbers at the beginning, and sends the buffer to the client.
Code
Server:
Client
Test Result
The server console output:
The client console output:
Problem
If the buffer sent by the server is less than 1024 Bytes the client receives garbage instead of the expected numbers - even though the dump of the buffer on the server side shows the correct buffer contents.
It all works as soon as I use at least
1024
for the allocated buffer size (sending a lot of unneeded zeros).NOTE: The "1024" is not constant, that's the value I found works for this example. In my actual larger test code that does the full transfer the behavior is even more varied. I found when I use 64000 as the size it always works. The discrepancy in size between the Buffer and its ArrayBuffer (
message.data.buffer
) also is much larger there. Here it is just two bytes, in my stream test it's 9 vs. 57409, for example.Also note that the exact same code for the transfers and for the log statement works find for my larger code test example where I do an actual transfer - only the last chunk, the one I modeled here, causes the problem. So my general approach with how I write those numbers into the buffer and how I get them back on the client works, apparently.
Is it possible the underlying ArrayBuffer is not zeroed? So when I have a smaller buffer than before I get in trouble?
Other Clients Work!
µws as Client (works)
Client code slightly changed for
[µws](https://github.com/uNetworking/bindings/tree/master/nodejs)
, such aswss.clients.length
instead ofwss.clients.size
, and I get anArrayBuffer
not aBuffer
, it shows the expected result:Browser as Client (works)
The problem is the client side - the example works fine when I use the browser (Google Chrome).
Background Story (optional)
My use case - not really relevant but just for the background story: I send a binary stream over websocket and since the client may issue many different requests simultaneously each one gets an ID. Now I have to add that ID to each chunk of the binary stream . I do that by putting 9 Bytes in front of the actual chunk. It all works fine during the stream, when the buffers are large - but for some inexplicable reason the last message, supposed to signify the end (Byte 9 is the "end" flag, 0 during the stream, 255 for the last chunk) has both the numeric ID (Bytes 0...7) and the flag garbled. If I blow up the last chunk to be much larger than actually necessary it works.
The text was updated successfully, but these errors were encountered: