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

通过TCP传输方法调用的结果,tcp,racket,communication,Tcp,Racket,Communication,我想知道如何实现一种“远程方法调用”(以非常简单的形式)。我正在以面向对象的方式编写程序。我有对象生活在树莓圆周率和对象生活在我的电脑上。因此,有时我想从计算机上的对象向raspberry pi上的对象发送消息。到目前为止没有什么太难的。但是当我想让那条消息产生结果时,我被卡住了 例如,如何实现我的计算机上的一个对象正在向raspberry pi发送带有参数3和4的消息“add”,并期望得到结果(7) 我制定了一个协议,通过TCP向对象发送消息和参数。但是如果结果是预期的,我的Raspberry

我想知道如何实现一种“远程方法调用”(以非常简单的形式)。我正在以面向对象的方式编写程序。我有对象生活在树莓圆周率和对象生活在我的电脑上。因此,有时我想从计算机上的对象向raspberry pi上的对象发送消息。到目前为止没有什么太难的。但是当我想让那条消息产生结果时,我被卡住了

例如,如何实现我的计算机上的一个对象正在向raspberry pi发送带有参数3和4的消息“add”,并期望得到结果(7)

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

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

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

我可以用“消息表”扩展负责通信的对象(通过TCP)。在该表中,我可以存储每条消息的ID、消息本身、目标对象(在raspberry 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编写程序,也许使用call和current continuation更容易实现这一点(如果可能的话)?通过保留“未来”(仍然需要做的事情),直到结果被知道。

如果你想利用这个领域的其他工作,你可以使用RESTAPI

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

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

有相当多的指南可供在覆盆子上休息:


    • 一种可能的方法是,每个请求与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绑定任务。

      谢谢!我会问老师是否可以使用REST,但我想他不会同意(因为使用TCP是项目的一部分,也是最困难的部分)。你到底在问什么?如何进行非阻塞I/O?(回答:
      char-ready?
      byte-ready?
      )或者您是否在问,在远程计算机代表本地计算机进行计算的情况下,设计客户端/服务器程序的最佳方法是什么?我想设计一个非阻塞I/O。这就是为什么我保留一个消息“表”,以便在收到答复时使用(使用byte ready?了解是否有一些输入)我也把它放在表中。但无论如何,当我向raspberry pi发送消息等待回答时,我将不得不阻止该程序。否则我将不得不以异步方式重新设计我的程序。谢谢!我可以这样做,但我真的不明白在等待输入时如何做其他事情。我正在考虑捕获在做请求之前(使用call/cc),我可以继续做其他事情,然后当数据可用时,调用continuation。但这一切都变得有点复杂。你可以在等待输入的同时做其他事情,因为输入(以及尽可能多的“未来”的输入)将在与程序其余部分不同的线程中处理。