[英]Forward compatibility in storage size constrained protocol
我有一個簡單的協議,其中包含4個字段:
Field-1 (4-bits)
Field-2 (6-bits)
Field-3 (4-bits)
Field-4 (2-bits)
目前,我對它們進行了組織,因此它們按字節對齊為:
Field-1,Field-3,Field-2,Field-4
消息總共占用2個字節,開銷為0個字節。
為了使它向后兼容,因此我可以理解以前版本的消息,我在開頭添加了一個1字節的版本字段,它變為:
Version-Field,Field-1,Field-3,Field-2,Field-4
總共3個字節,開銷為1個字節。
如何增加前向兼容性,以便可以在協議的新版本中添加新字段,同時確保軟件的舊版本仍能以最低的開銷理解消息?
通常,您的協議會指定每個消息具有:
然后,該協議的每個新版本都允許您將新數據添加到與該協議的先前版本一致的前綴中,並且該協議的每個版本都必須指定如何識別其定義的數據的結尾(在您的示例中固定長度,因此很容易),並在將來的版本中定義數據的開頭。
為了處理消息,使用者檢查以確保它是足夠高的版本,處理它可以理解的前綴,並使用長度字段跳過其余部分。
對於像您的協議那樣受空間限制的事情,我可能會做這樣的事情:
第一個字節是4位最小版本和4位長度字段。
如果長度字段L在0-11中,則消息的其余部分為L + 1個字節長。
通過遵循以下規則確保嚴格的BC,您將擁有FC:
新版本必須保持以前版本的字段布局已知。
如果您可以遵守規則,那么您將自動擁有BC和FC。 因此,使用該規則,您只能通過將新字段附加到現有布局中來添加新字段。
讓我舉例說明。 假設您需要為版本2添加這些字段:
Field-5 (1-bit)
Field-6 (7-bits)
請記住規則,新字段只能追加到現有布局。 因此,這是版本2的消息布局:
Version-Field,Field-1,Field-3,Field-2,Field-4,Field-5,Field-6
因為版本1已知的布局是完整的,所以您的版本1代碼可以使用此(偽代碼)讀取任何版本的消息:
function readMessageVersion1(byte[] input) {
var msg = {};
msg.version = input[0];
msg.field1 = input[1] & 0x0f;
msg.field3 = input[1] >> 4 & 0x0f;
msg.field2 = input[2] & 0x3f;
msg.field4 = input[2] >> 6 & 0x03;
return msg;
}
版本1不需要檢查版本字段,因為已知的布局是無條件的。 但是,版本2和所有其他版本將需要檢查版本字段。 假設我們使用值2來指示版本2,則將這樣做(偽代碼):
function readMessageVersion2(byte[] input) {
var msg = readMessageVersion1(input);
//check version field
if (msg.version < 2) return msg;
msg.field5 = input[3] & 0x01;
msg.field6 = input[3] >> 1 & 0x7f;
return msg;
}
該代碼最重要的部分是它重用了先前版本的代碼,並進行了以下檢查:
if (msg.version < 2) return msg;
該代碼的版本3可以簡單地跟隨版本2,如下所示:
function readMessageVersion3(byte[] input) {
var msg = readMessageVersion2(input);
//check version field
if (msg.version < 3) return msg;
// read the input bytes here
return msg;
}
可以將其視為將來版本的模板。 通過遵循規則和示例,該協議的任何版本都可以從任何版本讀取消息,而僅需1個字節的開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.