15

Imagine that I have server and client talking via WebSocket. Each of time sends another chunks of data. Different chunks may have different length.

Am I guaranteed, that if server sends chunk in one call, then client will receive it in one message callback and vice-versa? I.e., does WebSocket have embedded 'packing' ability, so I don't have to care if my data is splitted among several callbacks during transmission or it doesn't?

yeputons
  • 8,478
  • 34
  • 67

2 Answers2

15

Theoretically the WebSocket protocol presents a message based protocol. However, bear in mind that...

  • WebSocket messages consist of one or more frames.
  • A frame can be either a complete frame or a fragmented frame.
  • Messages themselves do not have any length indication built into the protocol, only frames do.
  • Frames can have a payload length of up to 9,223,372,036,854,775,807 bytes (due to the fact that the protocol allows for a 63bit length indicator).
  • The primary purpose of fragmentation is to allow sending a message that is of unknown size when the message is started without having to buffer that message.

So...

A single WebSocket "message" could consist of an unlimited number of 9,223,372,036,854,775,807 byte fragments.

This may make it difficult for an implementation to always deliver complete messages to you via its API...

So whilst, in the general case, the answer to your question is that the WebSocket protocol is a message based protocol and you don't have to manually frame your messages. The API that you're using to use the protocol may either have message size limits in place (to allow it to guarantee delivery of messages as a single chunk) or may present a streaming interface to allow for unlimited sized messages.

I ranted about this back during the standardisation process here.

Len Holgate
  • 21,282
  • 4
  • 45
  • 92
  • 1
    old rant (circa 2011), most of the points are moot, invalid, or addressed now in the various real-world implementations of websocket. – Joakim Erdfelt Jan 09 '14 at 16:57
  • 1
    Well, we'll agree to disagree I think, unless you fancy commenting on the blog post in question and pointing out how it's now incorrect; then we can discuss. The fact that implementations CAN and DO come up with their own work arounds (such as message size limits) doesn't doesn't detract from the fact that the protocol spec ALLOWS for the behaviour shown above and, IMHO, that's unfortunate and should/could have been dealt with at the time. – Len Holgate Jan 09 '14 at 17:05
  • I guess all involved in the discussion here are what I'd call experts on networking and WebSocket;) But I do like to point out one thing for other readers: I guess it's worth distinguishing between _API_ and _protocol_. A WebSocket API can expose WebSocket at different levels: per-message, per-frame or streaming. And even with a streaming API, the implementation can expose message boundaries. And in any case, the WebSocket protocol itself is message (and frame) based. And it _requires_ message boundaries to be preserved - but not frame boundaries. – oberstet Jan 09 '14 at 19:47
  • Indeed. However the original question muddies the waters a little by asking about how the implementation will deliver the messages to user code. – Len Holgate Jan 09 '14 at 21:11
10

WebSocket is a message-based protocol, so if you send a chunk of data as the payload of a WebSocket message, the peer will receive one separate WebSocket message with exactly that chunk of data as payload.

oberstet
  • 21,353
  • 10
  • 64
  • 97
  • I would be interested in a concrete confirmation of this behavior circa 2022 in Firefox and Chrome. Happen to know? – Todd Freed Feb 02 '22 at 05:45
  • 1
    yes, still like that, as the API in browsers available to any JavaScript is still the same, and that API is WebSocket message based, your JavaScript callbacks that you use to observe the WebSocket connection fires per-websocket-message. There is no API (to my knowledge) to get at individual WebSocket frames, or individual TCP/TLS segments, or individual IP packets. – oberstet Feb 02 '22 at 17:15