Creating a Multi-Language, Serverless Chat Program - Part 1: Protocol Design
Written By: Nathan Baker
- 11 Aug 2006 -
Description: In order to explore how different languages approach GUI programming, network sockets, and object-oriented concepts, we will embark on a journey in creating a serverless chat protocol, and clients for it in many different languages. This is the first installment, where I describe the protocol and the project.
The Network Format
Well, you're probably horribly bored by now, but congratulations! We're almost done with the design work now. All that's left is to talk about what things look like when they're going "over the wire", which means out on the network. It is important that this be well-specified, because otherwise the receiving end will just see a bucket o' bits and have no idea what to do with it. I'm going to brush over this pretty fast to keep you from falling asleep and drooling into your keyboard, which would be pretty gross, and possibly damage it.
The first thing to keep in mind is that not all computers interpret bytes the same way. This concept of endianness is addressed in the Internet Protocol, which specifies that bytes should be sent in the big-endian byte order. Now that the consumer market is dominated (saturated?) by PCs that natively use little-endian formats, this seems questionable, but might as well play along. Numbers will be sent in network order, and strings will be sent as UTF-8 Unicode strings, prefixed by the number of bytes in the string (in network order, of course). Not all languages are Unicode-friendly. These strings can be handled internally in whatever way the implementer wants, but they must be kept pristine for when communicating with Unicode-aware clients. All strings originating from non-Unicode-friendly clients must at least be ASCII, since ASCII is upwards-compatible with UTF-8 on transmission (though not on reception).
Users
A user contains four pieces of information (yes, I know I said three earlier. Hush). To keep you from having to read up, the three mentioned are the server instance, the name, and the status.
The server instance is not transmitted when a user is serialized (serialized is a fancy word for "converted into bytes"). Each server should already know, or be able to figure out by the direction of the message, how to reach the user. The name is transmitted as a string, which is described above. The status is actually two items (hence the 4-item total): a status message and an away bit. The status message is a string, and the away bit is a Boolean item indicating whether the user is away or not.
Messages
A message is actually a single byte plus a 'payload'. This byte represents the type of message (recall that messages are typed with 256 possible types). The byte may be followed by more data, depending on the type, included in the payload. This is always begun by the number of bytes in the payload (this must be zero for a zero-byte payload), interpreted as a 32-bit signed integer. I hate using signed values for things that cannot possibly be less than zero, but not all languages support the concept of unsigned numbers, so for the sake of maximum compatibility we will limit ourselves. Practically speaking this should not matter, as the maximum value of a 32-bit signed integer is over two billion, and if you are sending messages over two gigabytes in size, something is wrong. After this length specifier come the actual data, if any.