Choice of transports for JSON over TCP

前端 未结 5 1171
小鲜肉
小鲜肉 2020-12-24 03:16

I\'m writing a simple streaming JSON service. It consists of JSON messages, sent intermittently, for a long period of time (weeks or months).

What is the best pract

相关标签:
5条回答
  • 2020-12-24 03:46

    When you want to serve browser clients, the closest you get to raw TCP is WebSockets.

    WebSockets has sufficient momentum that browser vendors will improve support (Chrome 14 and Firefox 7/8 support the latest protocol draft) and that a broad range of client and server frameworks will support it.

    There are already a couple of open-source client libraries, including Autobahn WebSocket.

    When you want to bake something for your own (on top of raw TCP), I would recommend a length-prefixed format for your JSON messages, i.e. Netstrings

    Disclaimer: I am author of Autobahn and work for Tavendo.

    0 讨论(0)
  • 2020-12-24 03:58

    You can use Server-Sent Events.

    var source = new EventSource('/EventSource');
    
    source.onmessage = function(e) {
      var data = JSON.parse(e.data);
      console.log(e.data);
    };
    
    source.onopen = function(e) {
      console.log('EventSource opened');
    };
    
    source.onerror = function(e) {
      console.log('EventSource error');
    };
    
    0 讨论(0)
  • 2020-12-24 03:59

    The first of four bytes of the message can be an 32-bit integer indicating size (in bytes) of the message. Then the receiver should follow these steps:

    1. Read the first four bytes of data and figure out the exact amount of bytes you need to read the whole message.
    2. Read the rest of the message and deserialize it as a JSON

    Sender code in C#:

            public void WriteMessage(Packet packet) {
            // Convert the object to JSON
            byte[] message = Encoding.UTF8.GetBytes(packet.Serialize());
    
            // Serialize the number of characters
            byte[] messageLength = BitConverter.GetBytes(message.Length);
    
            // Build the full message that will hold both the size of the message and the message itself
            byte[] buffer = new byte[sizeof(int) + message.Length];
    
            Array.Clear(message, 0, message.Length);
    
            // Print the size into the buffer
            for (int i = 0; i < sizeof(int); i++)
            {
                buffer[i] = messageLength[i];
            }
    
            // Print the message into the buffer
            for (int i = 0; i < message.Length; i++)
            {
                buffer[i + sizeof(int)] = message[i];
            }
    
            // Send it
            stream.Write(buffer, 0, buffer.Length);
        }
    
    0 讨论(0)
  • 2020-12-24 04:03

    my first two options would be:

    1. Do what early TCP protocols do: send one message (a JSON object in your case) and close the connection. The client detects it and reopens to get the next object.

      • pros: very easy to parse, no extra (content) bytes sent. any loss of data means losing just a single object. if you can stand that, there's no need to add retransmision to your app.
      • cons: if you send a (huge) lot of (very) small objects, the three-packet TCP handshake adds to latency.
    2. Do what chunked-mode HTTP does: first send the number of bytes in the JSON object, a newline (CRLF in HTTP), and your JSON object. The client just have to count bytes to know when the next byte would be the next objectsize.

      • pros: you keep one long-lived stream.
      • cons: a few extra bytes, you have to keep a long-lived stream, so accidental break and reconnection has to be handled as exceptional events, need to establish some handshaking to continue where it failed.
    0 讨论(0)
  • 2020-12-24 04:08

    I've codified what I and some other developers are doing:

    http://en.wikipedia.org/wiki/Line_Delimited_JSON

    It has the advantage of being netcat/telnet compatible.

    See also: http://ndjson.org/

    0 讨论(0)
提交回复
热议问题