通过TCP通信方法调用的结果



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

例如,如何实现我的计算机上的一个对象向树莓派发送带有参数3和4的消息"add",并期望得到结果(7)?

我制作了一个协议,通过TCP向对象发送消息和参数。但是,如果预期结果,我的Raspberry Pi上的对象将不得不通过TCP发送一条新消息来回答。但是我怎样才能得到答案呢

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

因此,我在思考如何在不执行阻塞操作的情况下实现这一点我想出了这个:

我可以用"消息表"扩展负责通信的对象(通过TCP)。在该表中,我可以为每条消息存储ID、消息本身、目标对象(在树莓pi上)和结果

因此,现在,如果我想发送消息"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中编写程序,也许使用当前延续的调用是实现这一点的更容易的方法(如果可能的话)?通过保留"未来"(还有什么要做)直到结果揭晓。

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

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

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

有相当多的指南可用于复盆子上的REST:

  • https://thefloppydisk.wordpress.com/2013/05/08/how-to-build-a-restful-web-api-on-a-raspberry-pi-in-javascript/
  • http://www.instructables.com/id/Building-a-Web-Enabled-Door-Lock-using-Rest-API-an/
  • http://www.gaggl.com/2014/04/raspberrypi-real-world-control-with-rest-api/

一种可能的方法是每个请求到Raspberry Pi建立一个连接,两端每个连接建立一个线程。所以在电脑上,你的发送信息会被定义为这样的:

(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绑定任务。

相关内容

  • 没有找到相关文章

最新更新