我在c#中的TCP客户端应用程序返回时遇到了一个大问题。正常情况下它工作正常,但在某些情况下,服务器向特定客户端发送同时响应,因此这种情况下所有同时响应都在客户端作为单个消息接收。因此,客户端无法识别单个消息。所以这样的情况我的客户端应用程序无法处理特定的活动。是否可以在客户端读取单个消息?所以为了解决这个问题,我有一些选择,但我不知道它是否正确。
1-在客户端使用固定长度的缓冲区(但我的消息是可变长度)。
2-为每条响应消息添加分隔符。
如果有人知道解决此类问题的解决方案,请帮助我。
答案 0 :(得分:5)
TCP是基于流的,您从客户端到服务器获得数据流。如果你不能建立一个应用程序协议来确保每个发送的消息是单独的(这通常不是一个明智的想法,使用TCP),你需要“反序列化”你期望从流中得到的东西。
因此,您需要向每条消息发送一些信息,以便您区分数据。这通常通过每条消息开头的标记或类型数据来完成。有时一个字节会起作用(取决于你有多少种不同的消息类型)。然后,您从流中读取该字节,然后决定接下来要反序列化的内容。例如如果要发送字符串,可以序列化'1',然后string
。如果您想发送日期/时间,可以序列化'2'然后DateTime
。在服务器上,如果这两个对象大约在同一时间发送,您可以简单地反序列化byte
,如果它是'1',则反序列化string
,然后继续反序列化:获取下一个byte
,如果是'2',则反序列化DateTime
。
重要的是要记住TCP是基于流的协议,而不是基于消息的协议。基于消息的需要在应用程序级别实现 - 例如。像上面这样的东西。
通过“序列化”和“反序列化”,我指的是.NET文档中Serializing Objects中描述的典型内置序列化器和反序列化器。对于JSON.NET或内置DataContractJsonSerializer
和JavaScriptSerializer
等库中包含的JSON序列化程序也是如此。
答案 1 :(得分:0)
只需确保每条消息的长度都是前几个字节,这样就可以将整个消息拆分为单个消息。
例如,假设您从服务器收到此20字节消息:
1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 2 | 4 | 6 | 1 | 5 | 3 | 3 | 2 | 6 | 3 | 4 | 1 | 6 | 2 | 3 | 5 | 3 | 0 | 4 | 6 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
^ ^ ^ ^ ^ ^
第一个字节表示第一个消息有2个字节的数据,因此您可以将该消息作为字节1和2进行检索。接下来,您读取字节3,它告诉您第二个消息只有1个字节的附加数据(字节) 4)。第三个和第四个消息有3个字节的数据(如字节5和9所示),然后是2个字节的消息和3个字节的消息。
答案 2 :(得分:-1)
使用至少包含体长的固定长度标头是最简单的方法。然后,根据正文,您可能需要其他信息(如果您想使用类似JSON来序列化/反序列化实际消息,则可以使用类型名称。)
如果您不想自己照顾好一切,可以使用像mine这样的网络库。向下滚动到文章末尾以查看JSON RPC示例实现。您可以将大部分内容用于获取基于JSON的通信渠道。