Building a Message Server with JRPC
This tutorial demonstrates how to build a simple message server and client using JRPC. This is a "Hello World" example - for more elaborate examples, download the SDK and explore the code under the samples/ directory.
📋 Step 1: Define the RPC Interface
Create the interface definition file msg.x:
program msgserv {
version MSGSERV_V1 {
string sendmsg(string) = 2;
} = 1;
} = 1234567;
This interface defines an RPC program with a single procedure sendmsg.
The client sends a string to the server, and the server returns a string back.
The C/C++ version of the Msg client/server is available from the Netbula ONC RPC For Win32 SDK.
⚙️ Step 2: Compile with jrpcgen
Run the jrpcgen compiler to generate Java classes:
jrpcgen msg.x
Generated Files:
msgserv.java
RPC program interface definition with constant definitions
msgserv_cln.java
Client stub class that implements the RPC interface
msgserv_svcb.java
Abstract RPC service class that needs implementation
👨💻 Step 3: Code the Client Application
Create the client application ClientTest.java:
import netbula.ORPC.*;
import java.net.*;
public class ClientTest {
static public void main(String args[]) {
try {
// Create client connecting to server using UDP protocol
msgserv_cln cl = new msgserv_cln(args[0], "udp");
/*
// Optional authentication
cl.setAuth(new AuthUnix("localhost", 501, 100, new int[2]));
*/
String msg = "hello world\n";
System.out.println("sending.. ");
// Send multiple messages
for(int i = 0; i < 5; i++) {
String reply = cl.sendmsg(msg);
System.out.println("got " + reply + "\n");
}
} catch (rpc_err e) {
System.out.println("rpc: " + e.toString());
}
}
}
This client connects to the Msg server on the specified host using UDP protocol, sends a message, and prints the reply. The client sends multiple messages in a loop.
🔧 Step 4: Compile the Client
Compile the client application:
javac ClientTest.java MSGSERV_1.java
Make sure the netbula.ORPC package is in the classpath by adding
the orpc.jar file to the CLASSPATH environment variable.
🚀 Step 5: Run the Client
Ensure the Msg server (C version or Java version) is running on localhost
Run the client:
java ClientTest
If the server is running, you should see the client print out replies from the server. Otherwise, it will print an RPC error: "Program not registered."
🖥️ Step 6: Code the Server
Create the server implementation msgsvc.java:
import netbula.ORPC.*;
class msgsvc extends msgserv_svcb {
// Implement the server function - echo the message back
String sendmsg(String msg) {
System.out.println("got msg from client " + msg);
return msg;
}
// Main function runs the server
public static void main(String argv[]) {
// Run the server using the run() method in Svc
// For more flexibility, use TCPServer and UDPServer directly
new msgsvc().run();
}
}
The server simply echoes back the received message. The run() method
handles all the server initialization and request processing.
⚡ Step 7: Compile and Run the Server
# Compile the server
javac msgsvc.java
# Run the server
java msgsvc
📁 Advanced Example: File Transfer Server/Client
Next, let's look at a more interesting example: a JRPC server/client that transfers
multiple files via RPC mechanism. This example is under the samples/filexfer
directory of the JRPC package.
File Transfer Interface
Interface definition file filexfer.x:
%import netbula.ORPC.*;
struct NFiles {
XDTFile files<>;
};
program FileXFER {
version v1 {
void xferFile(NFiles) = 1;
} = 1;
} = 12345678;
This interface defines a struct NFiles containing a variable-length
array of XDTFile objects. The xferFile function can
transfer any number of files in a single RPC call.
File Server Implementation
Server code FileServer.java:
import netbula.ORPC.*;
import java.io.*;
public class FileServer extends filexfer_svcb {
public void xferfile(NFiles in_arg) {
for(int i = 0; i < in_arg.files.length; i++) {
System.out.println("Received file: " +
in_arg.files[i].receivedFilepath() +
" " + in_arg.files[i].byteCount() +
" bytes transfered");
System.out.println("saved file: " +
in_arg.files[i].savedFilename());
}
}
static public void main(String args[]) {
rpc_err.debug = true;
FileServer server = new FileServer();
try {
server.run();
System.out.println("server exited");
} catch(rpc_err e) {
System.out.println("Fail to run server:" + e.toString());
}
}
}
File Client Implementation
Client code FileClient.java:
import netbula.ORPC.*;
public class FileClient {
static public void main(String args[]) {
try {
if(args == null || args.length < 2) {
System.out.println("Usage: java fileClient server_hostname file1 [file2 file3 ..]");
System.exit(1);
}
String servhost = args[0];
// Use TCP (UDP is not reliable for file transfer)
filexfer_cln cl = new filexfer_cln(servhost, "tcp");
System.out.println("Connected to " + servhost);
// Send files listed on command line to server
NFiles nf = new NFiles();
nf.files = new XDTFile[args.length - 1];
for(int i = 0; i < args.length - 1; i++) {
nf.files[i] = new XDTFile(args[i + 1]);
}
cl.xferfile(nf); // Send all files over
for(int i = 0; i < args.length - 1; i++) {
System.out.println(args[i + 1] + " " +
nf.files[i].byteCount() + " bytes sent");
}
} catch (Exception e) {
System.out.println("rpc: " + e.toString());
e.printStackTrace();
}
}
}
🎯 Summary
This file transfer example demonstrates how JRPC can handle complex data types
and transfer multiple files efficiently. The XDTFile class handles
all the file serialization and deserialization automatically.