更改此协议以使用TCP流

时间:2012-05-24 20:04:40

标签: c++ tcp

我为我的游戏制定了一个简单的协议:

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'之后的长度或读取字节直到读取长度字节。

您怎么看?

看起来效果很好。

1 个答案:

答案 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