Protocol Versioning
When you design a network protocol, your hope should be to produce something which will live on long past your initial application. Sometimes it's a proprietary protocol which is used only by your company. Other times it's a protocol you hope will evolve into a standard, such as TCP or IPv6.
In order to assure a long lifetime for your protocol, and the ability to repair or extend it, you MUST figure out how to identify the version of the protocol being spoken at each end of a connection, and what to do when different versions match. Without this capability you wind up with mismatched clients in the world which behave poorly or - in the worst case - open up vulnerabilities because of their inability to identify the way packets were constructed.
If you have a connection-oriented protocol, versioning is straight-forward. In your initial handshake, include a version number. When you establish a connection check to make sure the version numbers match, and break the connection if the versions are incompatible. If you want to be fancy, you can even have the two clients negotiate the version of the protocol to use.
Life is trickier if you have a connectionless protocol. In this case you send a datagram for processing by a remote party without authoritatively knowing if that party understands your version of the protocol. In this case you should follow the basic dictum of network message processing. Paraphrases, it is: be strict in what you produce, and tolerant in what you receive. Make sure you adhere to all standards in messages you send. Be as flexible as possible when receiving and processing a packet, especially for a cross-platform protocol implementation. If your software can safely interpret and act upon the message, it should generally do so to maximize chances of interoperability.
How do you know if you can safely process a packet from a later version of the protocol than your own? Any of the following methods can help ensure this.
- Major / Minor Version. Require that all protocol implementations be able to understand any version of the protocol earlier than its own. A change in a minor version means an implementation with a matching major version number can still safely consume the data. In other words, client version 1.53 can safely process a message from client version 1.74. If you introduce a change which breaks backward compatibility, move to the next major version number. For example, from 1.74 to 2.00.
- 'Must understand' flag. You can set a flag marking a particular field of the message or negotiation as 'must understand.' If a client understands the field and how to process it, fine. Otherwise it must discard the message, and / or tear down the connection. Sometimes a 'must understand' flag is paired with a protocol version number, indicating the earliest acceptable protocol version for a message recipient.
Versioning is very painful to get wrong. Make sure your protocols make allowances for both non-breaking and breaking changes, and for ensuring pairs of network endpoints can safely converse.