10 JSON-RPC over TCP
The program in this example is built on top of two Cminor system libraries:
the System.Net.Sockets library and
the System.Json library.
10.1 System.Net.Sockects Library
The sockets library contains minimal functionality contained by the following classes
most of which are found also in the .NET Framework:
-
TcpSocket class represents a TCP socket.
-
TcpListener class is for listening and accepting connections to a TCP port.
-
TcpClient represents an endpoint of a TCP connection.
-
NetworkStream is used to send and receive data over a TCP connection.
Here's the interface of the System.Net.Sockets library:
10.2 System.Json Library
This library contains classes for representing JSON data, a JSON parser, and classes for implementing the JSON-RPC 2.0 protocol over a TCP connection.
The following classes are for representing JSON data:
-
System.Json.Value class acts as an abstract base class of concrete JSON value classes.
-
System.Json.String class contains a JSON string.
-
System.Json.Number class contains a JSON number.
-
System.Json.Object class holds a map of JSON strings mapped to JSON values.
-
System.Json.Array class holds an array of JSON values.
-
System.Json.Bool represents a JSON truth value.
-
JSON null value is represented by null.
Here's the interface of the JSON data classes:
The ParseJsonText parses a JSON string and returns the corrensponding JSON value derived from the System.Json.Value class.
Each JSON value class override the ToString() member function that serialize the value as a string.
The following classes are for implementing the JSON-RPC 2.0 protocol:
-
System.JsonRpc.Exception is the base class of protocol error exception classes.
-
System.JsonRpc.InvalidRequest exception is thrown on invalid request.
-
System.JsonRpc.MethodNotFound exception is thrown when no method of given name is registered with TcpServer.
-
System.JsonRpc.InvalidParams exception is thrown by the application class when there is error with request parameters.
-
System.JsonRpc.Request class is for constructing a JSON-RPC request.
-
System.JsonRpc.Response class is for constructing a JSON-RPC response.
-
System.JsonRpc.Servant class is an abstract base class for JSON-RPC method implementation classes.
-
System.JsonRpc.Client class is an abstract base class for JSON-RPC client implementation classes.
Here's the interface of the JSON-RPC classes:
The following classes implement the JSON-RPC 2.0 protocol over a TCP connection:
-
System.JsonRpc.TcpClient class implements the client side of the JSON-RPC 2.0 protocol with the help of a class derived from the
System.JsonRpc.Client class.
-
System.JsonRpc.TcpServer class implements the server side of the JSON-RPC 2.0 protocol with the help registered servant classes derived from
the System.JsonRpc.Servant class. The server starts a thread for serving each client connection so it's not suitable as a real TCP service
implementation.
Here's the interface of the JSON-RPC TCP classes:
10.3 Server Program
Here's an example implementation of a JSON-RPC 2.0 server that evaluates arithmetic expressions:
The server listens by default port 8080 and serves requests to evaluate method.
10.4 Client Program
Here's an example implementation of a JSON-RPC 2.0 client that gets arithmetic expressions from user, converts them to JSON-RPC requests and shows retrieved results:
10.5 Example Communication
Here's an example of compiling the solution and running the server program:
> cminor build --native JsonRpcCalc.cminors
> cminor run --native assembly/debug/JsonRpcServer.cminora --log
press CTRL-C to end...
servant for method 'evaluate' registered
listening port 8080
connection accepted
received request: {"id":0,"jsonrpc":"2.0","method":"evaluate","params":{"expression":"1 + 2"}}
sent response: {"id":0,"jsonrpc":"2.0","result":3}
received request: {"id":1,"jsonrpc":"2.0","method":"evaluate","params":{"expression":"1.0.0 + 2"}}
sent response: {"error":{"code":1,"data":"Parsing file '' failed at line 1:\n<expr>
expected:\n1.0.0 + 2\n ^","message":"error evaluating expression"},"id":1,"jsonrpc":"2.0"}
connection ended
Here's an example of running the client program:
cminor run assembly/debug/JsonRpcClient.cminora --log
connected to: localhost:8080
enter expression, or CTRL-Z to end
> 1 + 2
sending request: {"id":0,"jsonrpc":"2.0","method":"evaluate","params":{"expression":"1 + 2"}}
response string received: {"id":0,"jsonrpc":"2.0","result":3}
response received: {"id":0,"jsonrpc":"2.0","result":3}
1 + 2 = 3
enter expression, or CTRL-Z to end
> 1.0.0 + 2
sending request: {"id":1,"jsonrpc":"2.0","method":"evaluate","params":{"expression":"1.0.0 + 2"}}
response string received: {"error":{"code":1,"data":"Parsing file '' failed at line 1:\n<expr>
expected:\n1.0.0 + 2\n ^","message":"error evaluating expression"},"id":1,"jsonrpc":"2.0"}
response received: {"error":{"code":1,"data":"Parsing file '' failed at line 1:\n<expr>
expected:\n1.0.0 + 2\n ^","message":"error evaluating expression"},"id":1,"jsonrpc":"2.0"}
error 1 processing request 1: error evaluating expression:
Parsing file '' failed at line 1:
<expr> expected:
1.0.0 + 2
^
enter expression, or CTRL-Z to end
>