繁体   English   中英

开发基于TCP / IP的消息客户端的建议

[英]Suggestions for developing a TCP/IP based message client

我有一个控制电话系统的服务器端协议,我已经实现了一个与之通信的客户端库,该库正在生产中,但是目前我的系统存在一些问题,因此我正在考虑重新编写它。

我的客户端库当前是用Java编写的,但我正在考虑用C#和Java重写它,以允许不同的客户端访问同一后端。

以关键字开头的消息具有一定数量的元数据字节,然后具有一些数据。 消息始终以消息字符的结尾终止。

客户端和服务器之间的通信是双工的,通常采取来自客户端的请求的形式,该请求会引起服务器的多个响应,但也可以是通知。 这些消息被标记为:

C:命令

P:待处理(服务器仍在处理请求)

D:数据数据作为对

R:回应

B:忙(服务器太忙,无法处理响应)

N:通知

我当前的体系结构已解析了每个消息,并生成了一个线程来处理它,但是我发现某些通知的处理顺序不正确,这给我带来了一些麻烦,因为必须按到达时的顺序处理它们。

双工消息通常采用以下消息格式:客户端->服务器:命令服务器->客户端:等待(可选)服务器->客户端:数据(可选)服务器->客户端:响应(消息数据中的第二个条目表示是否是不是错误)

我使用该协议已有一年多了,但从未见过繁忙的消息,但这并不意味着它们不会发生。

服务器还可以向客户端发送通知,并且服务器上的事件会自动触发一些响应消息,因此无需发出相应的命令即可发送它们。

某些通知消息将作为消息序列的一部分到达,例如:

NotificationName M00001 NotificationName M00001 NotificationName M00000

字符串M0000X意味着将要发送更多数据,或者这是消息的结尾。

目前,tcp客户端相当笨,它仅生成一个线程来通知订阅者上的事件已接收到消息,该事件特定于message关键字和消息的类型(因此data,Responses和Notifications分别处理)这对于数据和响应消息相当有效,但由于通知消息似乎很快到达,并且由于竞争条件有时似乎导致消息结尾在处理包含数据的消息之前被处理,因此被通知消息所取代,导致丢失消息数据。

鉴于对系统工作原理的书面描述很差,您将如何编写客户端传输代码?

元数据没有消息号,并且由于供应商提供的协议,我无法控制其底层协议。

我只能推荐基于Java的解决方案。

我会使用一些已经成熟的传输框架。 我所说的“一些”是我迄今为止唯一使用过的产品-Apache MINA。 但是,它可以工作并且非常灵活。

关于无序处理消息-对于必须按接收顺序生成的消息,您可以建立队列并将此类消息放入队列。
要限制队列数量,您可以实例化4个队列,然后根据消息排序部分的哈希值的最后2位(表示0-3)将传入的消息路由到特定队列(例如,邮件中包含的client_id)。

如果您还有更具体的问题,我可以适当地更新我的答案。

消息必须按照接收顺序进行处理的要求几乎强制了生产者/消费者设计,即侦听器从客户端获取请求,进行解析,然后将解析后的请求放入队列中。 一个单独的线程(使用者)按顺序从队列中获取每个消息,对其进行处理,然后将响应发送给客户端。

或者,使用者可以将结果放入队列中,以便另一个线程(也许是侦听器线程?)可以将结果发送到客户端。 在这种情况下,您将具有两个生产者/消费者关系:

Listener -> event queue -> processing thread -> output queue -> output thread

在.NET中,使用BlockingCollection处理队列很容易实现。 我不知道Java是否有类似的东西。

多重消息请求的可能性使事情变得有些复杂,因为侦听器似乎必须将消息缓冲到请求的最后一部分进入,然后再将整个事物放入队列。

对我而言,生产者/消费者设计的优点在于,它迫使程序的不同部分之间进行硬性分隔,从而使每个部分的调试更加容易,并将共享状态引起问题的可能性降至最低。 这里唯一稍微复杂的部分是,您必须将连接(套接字或其他任何东西)作为在队列中共享的消息的一部分,以便输出线程知道将响应发送到哪里。

对于我来说,尚不清楚是必须按接收顺序处理所有消息,还是只需要按正确的顺序处理任何特定客户端的消息。 例如,如果您有:

Client 1 message A
Client 1 message B
Client 2 message A

在处理来自客户端1的第二条消息之前,可以处理来自客户端2的第一条消息吗? 如果是这样,则可以使用逻辑上多个队列(每个客户端一个)来提高吞吐量。 然后,您的“消费者”成为多个线程。 您只需要确保每个客户端在任何时间仅处理一条消息即可。

每个客户端我都会有一个线程来进行解析和处理。 这样,处理将按照其发送/到达的顺序进行。

如您所述,不能安全地并行执行任务。 在不同的线程中执行解析和处理可能会增加您可能节省的开销。

如果您的处理相对简单并且不依赖于外部系统,则单个线程应该能够每秒处理1K到20K消息。

您还有其他要解决的问题吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM