我为我的游戏制定了一个简单的协议:
b = bool
i = int
sINT: = string whose length is INT followed by a : then the string
m = int message id.
示例:
m133s11:Hello Worldi-57989b0b1b0
这将是:
Message ID 133
String 'Hello World' length 11
int -57989
bool false
bool true
bool false
但我不知道TCP可能只发送消息的PART。我不确定如何修改它,以便我可以执行以下操作:
on receive data from client:
use client's chunk parser
process data
if has partial message then try to find matching END
if no partial messages then try to read a whole message
for each complete message in queue, dispatch it
我可以通过在消息开头添加B而在结尾处添加E,然后解析第一个char为B并且最后为E来实现此目的。
唯一的问题是如果 我收到的东西很傻,不符合协议。或者,如果我本来应该收到的东西不是消息而只是一个字符串。因此,如果我以某种方式接收字符串HelloB,那么我会将其解析为hello和消息的开头,但我永远不会收到该消息,因为它不是消息。
我如何修改协议以解决这些潜在问题?尽管我预计只会接收到正确形成的消息,但如果编码不当并将所有内容设置为重击,那将是一场噩梦。
由于
我决定在开头添加长度并跟踪我是否正在处理消息: 这样:
p32m133s11:Hello Worldi-57989b0b1b0
然后我有3个状态,读取找到'p',读取找到'p'之后的长度或读取字节直到读取长度字节。
您怎么看?
看起来效果很好。
答案 0 :(得分:1)
你在做什么是相当老派,磁带的东西。好的。
您可能遇到的问题是,如果收到邮件的一部分,您无法判断您是否在令牌中途。
E.g。如果收到:
m12
此消息是12,还是消息122的第一部分?
如果收到:
i-12
这是一个整数-12还是整数-124354的第一部分?
所以我认为您需要更改它以使消息编号是固定宽度(例如四位数),字符串长度是固定的(例如6位数),整数宽度固定为10位数。
所以你的例子是:
m_133s____11:Hello Worldi____-57989b0b1b0
这样,如果您收到消息的第一部分,您可以存储它并等待处理剩余部分。
您还可以考虑使用控制字符来分隔邮件部分。通常使用ascii控制代码,RS,FS,GS和US。所以消息可以是
[RS]FieldName[US]FieldValue[RS]fieldName[US]FieldValue[GS].
您知道何时有完整的消息,因为[GS]标志着结束。然后,您可以使用[RS]作为分隔符将其划分为字段,并使用[US]将每个字段拆分为名称/值。
有关简要信息,请参阅http://en.wikipedia.org/wiki/C0_and_C1_control_codes。