On Protocol-Design

„Line based“ (gross oversimplification) Protocols are hard to get right. For example I was sending some messages to an Acitve MQ server via the Stomp protocol and reading them back. The publisher was sending four simple messages:

40133518:Freigabe ueber das web
40133776:implizite Freigabe ueber das web
40133549:implizite Freigabe ueber das web
40133518:implizite Freigabe ueber das web

The (simple minded) subscriber was reading only three messages:

40133518:Freigabe ueber das web

40133776:implizite Freigabe ueber das webx00nMESSAGEndestination:/queue/ERP.warenbewegung.vorgangsfreigabenreceipt:msgid-237273336-1184938322.129923ntimestamp:1184934438616npriority:0nexpires:0nmessage-id:ID:hurricane.local.hudora.biz-57543-1181982245700-5:366695:-1:1:1nn40133549:implizite Freigabe ueber das web

40133518:implizite Freigabe ueber das web

So my code is obviously broken. But also the protocol is misdesigned in a way which makes it unnecessary hard to write decent clients.

The Stomp Protocol as the most informal Specification constisting basically just of a bag of examples. The Specification for example speaks of <key>:<value> pairs, while the examples use something like session: <session-id>. Observe the space between the colon and the value.

The specification explains that communication is based on frame, frames have headers and „null indicates the end of the frame“. So the strategy is to to read untill null (x00) and than break the data being read into header and body.

But, bodies can contain null bytes! So the specifications states: „It is recommended that MESSAGE frames include a content-length header which is a byte count for the length of the message body. If a content-length header is included, this number of bytes should be read, regardless of whether or not there are null characters in the body. The frame still needs to be terminated with a null byte, and if a content-length is not specified the first null byte encountered signals the end of the frame.“ (Actually implementations seem to expect ‚x00n‘ at the end of a frame)

So if reading ‚till the first null byte you can’t be sure you have read the whole frame until you parsed the frame headers to look for the content-length header! Also there is no „read_until_null“ command available in networking APIs. So you basically have to read input byte wise and check if you have seen a null or alternatively come up with some fancy buffering. This type of protocol design is not unusual (e.g. HTTP is of the same design) but this doesn’t make it better. And this design makes it very hard to build correct, reliable, high-performance protocol.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:


Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )


Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )


Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s