RPC 在 C 中就地更改值

Posted

技术标签:

【中文标题】RPC 在 C 中就地更改值【英文标题】:RPC to have values changed in-place in C 【发布时间】:2016-07-05 12:29:40 【问题描述】:

背景

我正在为一个类编写一个基本的 RPC 客户端/服务器代码,其中一个要求是服务器端必须就地更改值。最终目标是将向量从客户端传递到服务器。但由于我只是学习 RPC,所以我决定从基本示例开始。下面我有一个简单的代码,我在其中计算一个数字的平方。对于此示例,我想已经就地更改结果。

问题

正如您在我的server.c 中看到的,我尝试就地更改值。但是对于那些了解 C 的人来说,你已经可以看到我没有成功。调用 ./client localhost 4 时,我的结果是 4,由于我打印的值与我假设更改的相同,因此我预计它不再是 4。我怎样才能正确地就地更改值?

client.c

#include  <rpc/rpc.h>
#include  "square.h"

int
main(int argc, char **argv)
  
CLIENT      *cl;
square_in   in;
square_out  *outp;

if (argc != 3)
    //err_quit("usage: client <hostname> <integer-value>");
    exit(0);

cl = clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, "tcp");

in.arg1 = atol(argv[2]);
if ( (outp = squareproc_1(&in, cl)) == NULL)
    //err_quit("%s", clnt_sperror(cl, argv[1]));
   exit(0);

printf("result: %ld\n", in.arg1);
exit(0);
 

server.c

// SERVER FILE: server.c

#include"rpc/rpc.h"
#include"square.h"
#include"stdio.h"
#include"stdlib.h"
#include"math.h"

square_out *squareproc_1_svc(square_in *inp,struct svc_req *rqstp)


    static square_out out;
    out.res1 = inp->arg1 * inp->arg1;
    inp->arg1 = out.res1;
    return(&out);

square.x

struct square_in 
 long arg1;
 ;

struct square_out 
long    res1;
;

program SQUARE_PROG 
version SQUARE_VERS 
square_out  SQUAREPROC(square_in) = 1;
                    /* procedure number = 1 */
 = 1;              /* version number = 1 */
 = 0x31230000;         /* program number = 0x31230000 */

【问题讨论】:

【参考方案1】:

服务器代码通常在不同的进程中,即使在不同的机器上,所以它不是“在同一个地方”,因此它可以写入客户端的内存。服务器接收的参数实际上是一个指针,指向客户端传递的数据的副本。所以服务器正在修改服务器进程地址空间中的一个副本,这对客户端进程地址空间中的原始数据没有影响。

有些接口定义语言允许您将参数注释为输出参数或输入/输出参数,因此生成器工具将编写期望服务器可以写入参数寻址的内存的代码,因此它应该发送该数据返回给客户端,并将其复制到客户端传入的内存中。但是,您似乎正在使用 ONC RPC 或类似的,并且不清楚它的 RPC 语言 (RPCL) 是否支持 out-params。请参阅rpcgen,第 6.7 节:

procedure:
    type-ident procedure-ident "(" type-ident ")" "=" value

请注意,支持 out-params 的 IDL 和相关的生成器工具并不真正允许服务器“就地”更改客户端的内存。服务器的结果仍然必须在进程之间传输,通常是通过网络传输。从客户端和服务器代码的角度来看,这些仅提供了超出参数的错觉。所以你的要求是可疑的,也许没有明确说明。

编辑:

如果确实需要服务器修改客户端的内存:

    确保服务器和客户端在同一台机器上运行。 使用特定于操作系统的共享内存 API(例如 shm_open() 和 mmap())将同一块物理内存映射到客户端和服务器的地址空间。 使用 RPC 传输共享内存的标识符(名称)(不是内存中的实际数据)并调用服务器的处理。 当客户端和服务器都打开并映射内存时,它们都有指向同一物理内存的指针(可能在不同的地址空间中具有不同的值),因此服务器将能够读取客户端写入的内容(无需复制或传输),反之亦然。

【讨论】:

以上是关于RPC 在 C 中就地更改值的主要内容,如果未能解决你的问题,请参考以下文章

就地更改Mongodb查询结果[重复]

就地更改Mongodb查询结果[重复]

包含 data.table 名称的变量已就地更改? [复制]

在Python列表中进行就地修改

$ sed -i 不更改文件

使用 jq 就地修改 json 中的键值