问题
background
I am writing a basic RPC client/server code for a class and one of the requirements is that the server side must change the values in-place. The final goal is to pass a vector from the client to the server. But since I am just learning RPC, I decided to start from basic examples. Below I have a simple code in which I compute the square of a number. For this example I'd like to change the result in-place already.
issue
As you can see in my server.c
, I tried to change the value in-place. But for those who know C, you can already see I had no succcess. When calling ./client localhost 4, my result was 4, and since I am printing the same value I supposely changed, I had expected it to be no longer 4. How can I correctly change the value in-place?
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:
The server code is typically in a different process, even on a different machine, so it's not "in the same place" such that it could write into the client's memory. The argument the server receives is actually a pointer to a copy of the data passed by the client. So the server is modifying a copy in the server process's address space, which has no effect on the original data in the client process's address space.
There are interface definition languages that let you annotate parameters as out-params or in/out-params so the generator tool will write code that expects the server may write into the memory addressed by the parameter, so it should send that data back to the client and copy it into the memory passed in by the client. However, it appears you are using ONC RPC or similar, and it's not clear that its RPC Language (RPCL) supports out-params. See rpcgen, section 6.7:
procedure:
type-ident procedure-ident "(" type-ident ")" "=" value
Note that an IDL and associated generator tool that support out-params do not truly allow the server to change the client's memory "in-place". The server's results must still be transmitted between processes, often over the network. These provide only the illusion of out-params from the perspective of the client and server code. So your requirement is dubious, perhaps not clearly stated.
EDIT:
If you truly need the server to modify the client's memory:
- Ensure the server and client run on the same machine.
- Use OS-specific shared-memory APIs such as shm_open() and mmap() to map the same chunk of physical memory into the address spaces of both the client and the server.
- Use RPC to transmit the identifier (name) of the shared memory (not the actual data in the memory) and to invoke the server's processing.
- When both client and server have opened and mapped the memory, they both have pointers (likely with different values in the different address spaces) to the same physical memory, so the server will be able to read what the client writes there (with no copying or transmitting) and vice versa.
来源:https://stackoverflow.com/questions/38203496/rpc-to-have-values-changed-in-place-in-c