2012-05-24 49 views
0

工作,我做了一个简单的协议,用于我的游戏:更改此协议与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可能只会发送一部分消息。我不知道我究竟怎么能修改此,这样我可以做到以下几点:

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 

我能做到这一点通过在结束的消息和E开头添加B,然后通过解析为第一个字符是B,最后是E.

唯一的问题是如果 我在中间接收到一些愚蠢的东西,而不遵循协议。或者,如果我应该只是收到一些不是信息的东西,而只是一个字符串。所以,如果我想以某种方式接收字符串HelloB,那么我会将其解析为hello和消息的开头,但我绝不会收到该消息,因为它不是消息。

我该如何修改我的协议来解决这些潜在的问题?尽管我预计只会收到正确形成的信息,但如果编码不好并且将所有信息都设置得不好,那将是一场噩梦。

感谢

我决定在开始添加的长度和跟踪,如果我工作的一个消息或没有的: 这样:

p32m133s11:Hello Worldi-57989b0b1b0 

我那么有3个状态,阅读找到'p',读取'p'后的长度或读取字节,直到读取长度字节。

您认为如何?

它似乎很好。

+0

使用协议缓冲区。或者,在开始时对整个数据包的长度和可能的校验和进行编码。但是,实际上,使用PB或其他建立的交换格式,没有重点发明车轮。 –

+0

我更喜欢使用我在这里所做的。 – jmasterx

+1

如果你真的不想使用预定义的协议,考虑用STX/ETX包装你的整个数据包http://en.wikipedia.org/wiki/C0_and_C1_control_codes – Chad

回答

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了解简短的信息。

+0

我决定在开头添加长度并跟踪如果我正在处理消息: so: p32m133s11:Hello Worldi-57989b0b1b0 然后,我有3个状态,读取以找到'p'长度字节已被读取。 你觉得呢? – jmasterx

+0

去吧。如果你得到一个非数字,你已经读完了这个长度。 – Ben