通过TCP传递方法调用的结果

时间:2015-03-29 12:53:08

标签: tcp racket communication

我想知道如何实现一种"远程方法调用" (以非常简单的形式)。我以面向对象的方式编写程序。我有生活在树莓派上的物品和生活在我电脑上的物品。所以 有时我想从计算机上的对象发送消息到覆盆子pi上的对象 。到目前为止没什么太难的。但 当我希望该消息产生结果时我会被卡住

例如,如何实现计算机上的对象发送消息"添加"使用参数3和4来覆盖树pi并期待结果(7)?

我制定了一个协议,通过TCP向对象发送消息和参数。但是如果预期结果,我的Raspberry Pi上的对象将不得不通过TCP发送新消息来回答。但是我能否抓住这个答案?

我可以使用/进行阻塞操作,将消息发送到Raspberry Pi并等待直到返回结果。但在模拟程序中,我猜这不是你想要的。

所以我在想 我可以 在不执行阻止操作的情况下实现此功能。 我想出了这个:

我可以扩展正在处理的对象(通过TCP)使用"消息表" 。在该表中,我可以为每条消息存储ID,消息本身,目标对象(在树莓派上)和结果。

所以现在如果我想发送消息" getNumber" (随机返回一个数字),我将使用消息和目的地调用通信对象。它将使用唯一ID,消息和目标填充表格。 在某个特定时刻,目标对象将完成计算并返回结果 要这样做,它会通过TCP将它的回答发送到通信对象,该通信对象将填充表中的结果。从那一刻开始,只需传递一个消息就可以请求消息的结果。 ID。所有通信对象都必须从他的表中读取结果。

没有通过TCP / IP进行通信,它看起来像:

(destination-object 'get-number) ; Results in a number, with TCP this could not have a result because the result itself also has to be send over TCP.

通过如上所述的沟通:

(define id ((communication-object 'send-message) "get-number" "destination-object"))
(define result ((communication-object 'get-result) id))

因为我从未制作过通过TCP / IP进行通信的程序,所以我想知道这是否是处理消息及其结果的好方法,或者是否有更好/更简单的方法。

知道我正在使用Racket编写程序,也许使用当前延续的调用是一种更简单的方法来实现它(如果可能的话)?保留"未来" (还有什么必须要做)直到结果已知。

2 个答案:

答案 0 :(得分:1)

如果您想利用此领域的其他工作,可以使用REST API。

这主要使用HTTP协议的机制,该协议在TCP之上运行,是浏览器用来连接网站的主要协议,为主机上的服务提供类似API的Web。 。返回结果是该体系结构的标准部分。

它不像TCP上的自定义协议那样轻量级,但另一方面,您将能够利用所有内置的错误和边缘案例处理以及大型用户社区。

Raspberry上有很多可用于REST的指南:

答案 1 :(得分:1)

一种可能的方法是对Raspberry Pi的每个请求建立一个连接,并在两端建立每个连接一个线程。因此,在PC上,您的发送消息将被定义为:

(define (send-message message-name . args)
     (let-values ((in-port out-port) (tcp-connect rasp-pi-addr port))
           ; Assuming you're sending Lisp values across the network
           (write (cons message-name args) out-port)
           (let ((result (read in-port)))
               (close-input-port in-port)
               (close-output-port out-port)
               result)))

...然后当您想要向Raspberry Pi发送请求时,您可以在一个帖子中执行此操作:

(thread (λ () (async-channel-put result-channel
                 ((communication-object 'send-message) "get-number" "destination-object"))))

然后,当这个操作发生时,你的程序的其余部分可以自由继续运行。您也可以在线程中执行任何您想要处理的结果,而不是让主线程等待结果:

(thread (λ ()
          (update-opponent-position
              ((communication-object 'send-message) "opponent" "make-move"))))

根据您的程序执行的操作,这可能会使您最小化所需的重新设计范围。

需要注意的是,Racket的线程不是真正的CPU线程,因此您不必通过使用它们来处理多个内核。但它们非常适合并行化I / O绑定任务。