我想知道如何实现一种"远程方法调用" (以非常简单的形式)。我以面向对象的方式编写程序。我有生活在树莓派上的物品和生活在我电脑上的物品。所以 有时我想从计算机上的对象发送消息到覆盆子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编写程序,也许使用当前延续的调用是一种更简单的方法来实现它(如果可能的话)?保留"未来" (还有什么必须要做)直到结果已知。
答案 0 :(得分:1)
如果您想利用此领域的其他工作,可以使用REST API。
这主要使用HTTP协议的机制,该协议在TCP之上运行,是浏览器用来连接网站的主要协议,为主机上的服务提供类似API的Web。 。返回结果是该体系结构的标准部分。
它不像TCP上的自定义协议那样轻量级,但另一方面,您将能够利用所有内置的错误和边缘案例处理以及大型用户社区。 p>
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绑定任务。