Search code examples
javascriptwebsocketurl-routingarraybuffer

how to route different data types over Websockets?


I have to send a lot of ArrayBuffers (audio voice data) over a websocket server. The Problem is, that the client has to know which type of ArrayBuffer the incoming data is (Uint8 / Uint16 / Float32...). The type can change on the fly if the user switch to an other audio quality.

What is the best way to inform the client about the array type ?

Ideas so far:

  • Put an extra prefix byte to the array (this might be slow because i have to create a new arrayBuffer for each audio chunk)
  • Using different routes like /16float or /uint8 to know which data is coming. (I have not found any information how this is done with websockets)

Is there an better way to do this? Can anyone give me an example how URL-Path routes with websockets work ?


EDIT: I implemented prefix bytes to send information about client and array type, but still interested in better/other solutions.


Solution

  • Cracker0dks, why are you using pure websockets and not a library. With primus you can use substream - namespace - which is more or less exactly what you want - you can also use binnary parser with primus.

    Socket.io is also an option but they are not as good as primus.(in my opinion)

    Currently its the most supported/ stable / complete solution for ws

     // server side:
    var primus
        , server
        , substream
        , http
        , Uint8
        , Uint16
        , Float32
        ;
    
    Primus = require('primus');
    http = require('http');
    substream = require('substream');
    
    server = http.createServer();
    primus = new Primus(server);
    
    primus.use('substream', substream);
    server.listen(8000);
    
    primus.on('connection', function (spark) {
        Uint8 = spark.substream('Uint8');
        Uint16 = spark.substream('Uint16');
        Float32 = spark.substream('Float32');
    
        Uint8.on('data', function (data) {
            console.log(data); //we recieve data from client on Uint8 ('to server') 
        });
    
        Uint16.on('data', function (data) {
            console.log(data); //we recieve data from client on Uint16 ('to server') 
        });
    
        Float32.on('data', function (data) {
            console.log(data); //we recieve data from client on Float32 ('to server') 
        });
    
        Uint8.write('to client'); // write data to client to Uint8
        Uint16.write('to client'); // write data to client to Uint16
        Float32.write('to client'); // write data to client to Float32
    
        //
        // piping data to Float32 
        //
        fs.createReadSteam(__dirname + '/example.js').pipe(Float32, {
            end: false
        });
    
        //
        // To stop receiving data, simply end the substream:
        //
        Uint16.end();
    });
    
    
    
    
    // client side:
    var primus
        , Uint8
        , Uint16
        , Float32
        ;
    primus = new Primus('server address');
    Uint8 = primus.substream('Uint8');
    Uint8.write('to server'); // write data to server to Uint8
    
    Uint16 = primus.substream('Uint16');
    Uint16.write('to server'); // write data to server to Uint16
    
    Float32 = primus.substream('Float32');
    Float32.write('to server'); // write data to server to Float32
    
    
    Uint8.on('data', function (data) {
        console.log(data); // you get data from server to Uint8 ('to client') 
    });
    
    Uint16.on('data', function (data) {
        console.log(data); // you get data from server to Uint8 ('to client') 
    });
    
    Float32.on('data', function (data) {
        console.log(data); // you get data from server to Uint8 ('to client') 
    });
    

    The above was taken from their documentation and changed to fit your example - i did not test it but it should work.

    I hope that help.