Skip to main content

How to write a simple RPC Programme?



    Writing an RPC(Remote Procedure Call) program is not so hard as it sounds.

If you are using Linux OS, it is really easy to do it. Look at the screenshots provided and follow the steps, then finally you will have a working RPC program.

Let the server procedure run as the localhost for this example. But you can customize the Linux command to interact with any other server you know of. It is simple.(Better to use the latest LTS version of Ubuntu if you do)

Step 1 : Check rpcinfo and install rpcbind

Before talking about rpcinfo let us see what rpcbind is.
  1. The rpcbind utility is a server that converts RPC program numbers into universal addresses. It must be running on the host to be able to make RPC calls on a server on that machine. When an RPC service is started, it tells rpcbind the address at which it is listening, and the RPC program numbers it is prepared to serve.
   To check the current RPC registration information known to the package rpcbind, we use the rpcinfo command.

Type the following command in the terminal to check this RPC registration information.

:-$ rpcinfo

This will show you the registration information in the terminal if it is successful.
                                           

Otherwise,
If you don't have the rpcbind package installed in your computer. You will be prompted to enter the following command.

:-$ sudo apt-get install rpcbind

This will install the rpcbind package in your computer, but make sure that it is connected with the internet. You can do this even if you are running your linux OS in a Virtual Machine.

                                       

You can see here that you may get an error saying E: unable to locate package rpcbind when you try the above command.

Then what you need to do is to run the following command in the terminal.

:-$ sudo apt-get update && apt-get upgrade

Then try the sudo apt-get install rpcbind command again and retype rpcinfo to verify the installation.



Step 2 : Write and compile your IDL file.

This is a sample IDL file which is used to create a simple calculator program where all the calculations happen at the server end.

/*The IDL File  --- name IDL.x*/

/*Structure to hold the 2 values to be used in computation*/

struct values{
    float num1;
    float num2;
    char operation;
};

/*Programme, version and procedure definition*/

program COMPUTE{
    version COMPUTE_VERS{
        float ADD(values) =1;
        float SUB(values)=2;
float MUL(values)=3;
float DIV(values)=4;
    } =6;

} = 456123789;

values ---> This is the name of the data structure to send the parameters of the computation to                                the server.

COMPUTE ---> This is the name of the programme.

COMPUTE_VERS ---> This is the name of the programme version.

ADD(values) ---> This is one of the methods that we are going to call remotely. The data                                                  structure containing the 2 operands and the operation to perform is given as                                          parameter to the remote method. This is similar for the other methods given                                          here as well.

You can see that at the end of each method and the programme and version, we have given some numbers. These numbers are used to uniquely identify each entity. You can give any number that you like here. 

When compiled using rpcgen compiler, this IDL file generates the

1. Client stub
2. Server skeleton
3. Sample client program
4. Sample server program
5. Header file
6.  XDR routines used by both the client and the server.
7. Makefile

        when executing the following command.

:-$  rpcgen -a -C IDL.x


Note the the name of our IDL file will be IDL.x. This command should be executed while your current directory is the directory where the IDL file is. Here we have used the C language (the -C in the Linux command is for this.)

If you type the command rpcgen in the terminal, you will see a set of commands that can be used with the rpcgen compiler as shown below.

                           

  The compilation of the IDL file will generate the above mentioned files in your current directory as shown below.
                                       


Step 3 : Edit the client and server programs.

This is the client program (IDL_client.c) that I have edited to suit our requirement of  writing a simple calculator which can add, subtract, multiply and divide. If you are familiar with C language, you can easily edit this program according to your needs.

#include "IDL.h"
#include <stdio.h>


float
compute_6(char *host,float a,float b,char op)
{
CLIENT *clnt;
float  *result_1;
values  add_6_arg;
float  *result_2;
values  sub_6_arg;
float  *result_3;
values  mul_6_arg;
float  *result_4;
values  div_6_arg;

if(op=='+'){

add_6_arg.num1=a;
add_6_arg.num2=b;
add_6_arg.operation=op;

clnt = clnt_create (host, COMPUTE, COMPUTE_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}

result_1 = add_6(&add_6_arg, clnt);
if (result_1 == (float *) NULL) {
clnt_perror (clnt, "call failed");
}

clnt_destroy (clnt);

return (*result_1);
}

else if(op=='-'){
sub_6_arg.num1=a;
sub_6_arg.num2=b;
sub_6_arg.operation=op;

clnt = clnt_create (host, COMPUTE, COMPUTE_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}

result_2 = sub_6(&sub_6_arg, clnt);
if (result_2 == (float *) NULL) {
clnt_perror (clnt, "call failed");
}

clnt_destroy (clnt);

return (*result_2);
}

else if(op=='*'){
mul_6_arg.num1=a;
mul_6_arg.num2=b;
mul_6_arg.operation=op;

clnt = clnt_create (host, COMPUTE, COMPUTE_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}

result_3 = mul_6(&mul_6_arg, clnt);
if (result_3 == (float *) NULL) {
clnt_perror (clnt, "call failed");
}

clnt_destroy (clnt);

return (*result_3);
}

else if(op=='/'){
if(b==0){
printf("You are trying to divide by zero. Please insert a valid number.\n");
exit(0);
}
else{
div_6_arg.num1=a;
div_6_arg.num2=b;
div_6_arg.operation=op;

clnt = clnt_create (host, COMPUTE, COMPUTE_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}

result_4 = div_6(&div_6_arg, clnt);
if (result_4 == (float *) NULL) {
clnt_perror (clnt, "call failed");
}

clnt_destroy (clnt);

return (*result_4);
}
}

}


int
main (int argc, char *argv[])
{
char *host;

float number1,number2;
char oper;
    printf("Enter the 2 numbers followed by the operation to perform:\n");
    scanf("%f",&number1);
    scanf("%f",&number2);
scanf("%s",&oper);

host = argv[1];
printf("Answer= %f\n",compute_6 (host,number1,number2,oper));
        exit(0);

}



The edited server program (IDL_server.c) is as follows.

#include "IDL.h"
#include <stdio.h>

float *
add_6_svc(values *argp, struct svc_req *rqstp)
{
static float  result;
result = argp->num1 + argp->num2;
return &result;
}

float *
sub_6_svc(values *argp, struct svc_req *rqstp)
{
static float  result;
result = argp->num1 - argp->num2;
return &result;
}

float *
mul_6_svc(values *argp, struct svc_req *rqstp)
{
static float  result;
result = argp->num1 * argp->num2;
return &result;
}

float *
div_6_svc(values *argp, struct svc_req *rqstp)
{
static float  result;
result = argp->num1 / argp->num2;
return &result;


}

Step 4 : Compile all the files

Now you need to compile all the files generated including the client and server programs that you edited above. Please make sure that you do not edit any other file which is generated by the rpcgen compiler.

For that, type the command

:-$ make -f Makefile.IDL

The output will be as shown in the following screenshot.

(All the object files will be created in the current directory)




 Step 5 : Run the server and the client

Now you can run the server in the same terminal using the following command.

:-$ sudo ./IDL_server

Open another terminal and run the client there.

:-$ sudo ./IDL_client localhost

(P.S.You will have to enter you password when prompted.)

Enter the 2 numbers that you want to compute followed by the relevant operator symbol for this simple calculator program. When you press enter, you will get the answer as shown in the following screenshot.



 So this is the simple calculator RPC program that you can try out quite easily in you Linux OS.


Comments

  1. Hey Tharika! Thanks a lot for the help. Everything was so aptly explained. Hats Off! :)

    ReplyDelete
  2. Can we use this program by making the server run in a different system and doing an RPC to the server from one system through lan? If yes, can you tell how?

    ReplyDelete
  3. Can we use this program by making the server run in a different system and doing an RPC to the server from one system through lan? If yes, can you tell how?

    ReplyDelete
  4. Yes Arjun, it is possible. You can do this by running the client with the relevant host name/ ip address of the machine in which the server runs (instead of localhost in the command sudo ./IDL_client localhost). I haven't tried it with this particular program myself, but you can try and confirm it here.

    ReplyDelete
    Replies
    1. I copied only IDL_Client object file to remote machine and tried to run with server ip but not working. Please elaborate if any file need to copy along with client object?

      Delete
    2. Vinod, I assume you copied the binary IDL_client, not the object file. I tested it, copied that file to hostB, then sudo ./IDL_client hostA (in hostA run this command, sudo ./IDL_server). It worked.

      Delete
  5. Is RPC support bi-directional communication. If yes, can you please tell me how to do that?

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Great example. Appreciate it.

    ReplyDelete
  8. Mam I am getting this when I COMPILED all the files.
    please help me in this.

    nihal@nihal-VirtualBox:~/Documents/Nihal FACE RPC$ make -f Makefile.IDL
    cc -g -c -o IDL_clnt.o IDL_clnt.c
    In file included from IDL_clnt.c:7:
    IDL.h:9:10: fatal error: rpc/rpc.h: No such file or directory
    9 | #include
    | ^~~~~~~~~~~
    compilation terminated.
    make: *** [: IDL_clnt.o] Error 1

    ReplyDelete
  9. I am getting this error do something.
    nihal@nihal-VirtualBox:~$ make -f Makefile.IDL
    cc -g -c -o IDL_clnt.o IDL_clnt.c
    In file included from IDL_clnt.c:7:
    IDL.h:9:10: fatal error: rpc/rpc.h: No such file or directory
    9 | #include
    | ^~~~~~~~~~~
    compilation terminated.
    make: *** [: IDL_clnt.o] Error 1
    nihal@nihal-VirtualBox:~$

    ReplyDelete
  10. } = 456123789;
    What this signify. Please elaborate

    ReplyDelete
  11. Indian people are very bad at teaching.

    ReplyDelete
  12. Hello, guys! I was facing this error after compiling the code: cc -g -c -o IDL_clnt.o IDL_clnt.c
    In file included from IDL_clnt.c:7:
    IDL.h:9:10: fatal error: rpc/rpc.h: No such file or directory
    9 | #include
    | ^~~~~~~~~~~
    compilation terminated.
    make: *** [: IDL_clnt.o] Error 1

    I found a solution to this problem, so I wanted to share the solution with those who faced the same issue:
    Use this code to compile the files instead: make -f Makefile.IDL CFLAGS="-I/usr/include/tirpc" LDLIBS="-lnsl -ltirpc"

    ReplyDelete

Post a Comment

Popular posts from this blog

How to connect my database instance with elastic beanstalk instance in AWS?

If you have deployed your web application in Elastic Beanstalk in AWS and now you need to connect a database to this instance, and your database is actually residing in a different instance, how can you actually connect them? It's easy with Elastic Beanstalk. I will explain an example scenario that I used for connecting my elastic beanstalk web application with another instance containing my MongoDB database. By looking at this, you can customize as per your need. Don't worry. This is easy. :) The only things you need here are the details about the 1. Database name that you need to connect to. Ex:- "myDB" 2. Port at which the database instance is listening. EX:- In the case of MongoDB, the listening port is 27017 3. Host name of your database instance. EX:- Like localhost, in this case, it will be the Public DNS of your database instance 4. The password of your database if exists. First these details need to be set as environment variables in Elastic Be

How to import the Public Certificate of one WSO2 product to the trust store of another?

To demonstrate this point, I will use the 2 products WSO2 API Manager 2.1.0 (referred as APIM from here onwards) and WSO2 Enterprise Integrator 6.1.1 (referred as EI from here onwards). When using EI as the Business Process Server during configuration of Workflows in APIM, one step to perform is to import the public certificate of EI to the truststore of APIM [1]. So now let's see how this can be done. Step 1: Go to <EI_HOME>/repository/resources/security/ folder and execute the following keytool command. This command is used to export the public certificate of EI as a certificate file called wso2carbon.cer. Since the default keystore in EI is wso2carbon.jks, we have specified it as the keystore and the default alias is wso2carbon. Provide wso2carbon as the keystore password when prompted as it is the default password. After executing the above command from within the security folder in EI, you will see that a file with the name of wso2carbon.cer is created