# Simple JSON-RPC Server

This is identical in usage (or should be) to the `SimpleXMLRPCServer` in the
Python standard library. Some of the differences in features are that it
obviously supports notification, batch calls, class translation (if left on),
etc.

:::{note}
The import line is slightly different from the regular
`SimpleXMLRPCServer`, since the `SimpleJSONRPCServer` is provided by the
`jsonrpclib` library.
:::

```python
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer

server = SimpleJSONRPCServer(('localhost', 8080))
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.register_function(lambda x: x, 'ping')
server.serve_forever()
```

To start protect the server with SSL, use the following snippet:

```python
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer

# Setup the SSL socket
server = SimpleJSONRPCServer(
    ('localhost', 8080), bind_and_activate=False)
server.socket = ssl.wrap_socket(
    server.socket, certfile='server.pem', server_side=True)
server.server_bind()
server.server_activate()

# ... register functions

# Start the server
server.serve_forever()
```

## A note on logging

`jsonrpclib-pelix` uses the `logging` module from the standard Python
library to trace warnings and errors, but doesn't set it up.
As a result, you have to configure the Python logging to print out traces.

The easiest way to do it is to add those lines at the beginning of your code:

```python
import logging
logging.basicConfig()
```

More information can be found in the
[logging documentation page](https://docs.python.org/3/library/logging.html).

## Notification Thread Pool

By default, notification calls are handled in the request handling thread.
It is possible to use a thread pool to handle them, by giving it to the server
using the `set_notification_pool()` method:

```python
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
from jsonrpclib.threadpool import ThreadPool

# Setup the thread pool: between 0 and 10 threads
pool = ThreadPool(max_threads=10, min_threads=0)

# Don't forget to start it
pool.start()

# Setup the server
server = SimpleJSONRPCServer(('localhost', 8080), config)
server.set_notification_pool(pool)

# Register methods
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.register_function(lambda x: x, 'ping')

try:
    server.serve_forever()
finally:
    # Stop the thread pool (let threads finish their current task)
    pool.stop()
    server.set_notification_pool(None)
```

## Threaded server

It is also possible to use a thread pool to handle clients requests, using the
`PooledJSONRPCServer` class.
By default, this class uses pool of 0 to 30 threads. A custom pool can be given
with the `thread_pool` parameter of the class constructor.

The notification pool and the request pool are different: by default, a server
with a request pool doesn't have a notification pool.

```python
from jsonrpclib.SimpleJSONRPCServer import PooledJSONRPCServer
from jsonrpclib.threadpool import ThreadPool

# Setup the notification and request pools
nofif_pool = ThreadPool(max_threads=10, min_threads=0)
request_pool = ThreadPool(max_threads=50, min_threads=10)

# Don't forget to start them
nofif_pool.start()
request_pool.start()

# Setup the server
server = PooledJSONRPCServer(
    ('localhost', 8080), config, thread_pool=request_pool)
server.set_notification_pool(nofif_pool)

# Register methods
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.register_function(lambda x: x, 'ping')

try:
    server.serve_forever()
finally:
    # Stop the thread pools (let threads finish their current task)
    request_pool.stop()
    nofif_pool.stop()
    server.set_notification_pool(None)
```

## Unix Socket

To start a server listening on a Unix socket, you will have to use the
following snippet:

```python
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
import os
import socket

# Set the path to the socket file
socket_name = "/tmp/my_socket.socket"

# Ensure that the file doesn't exist yet (or an error will be raised)
if os.path.exists(socket_name):
    os.remove(socket_name)

try:
    # Start the server, indicating the socket family
    # The server will force some flags when in Unix socket mode
    # (no log request, no reuse address, ...)
    srv = SimpleJSONRPCServer(
        socket_name, address_family=socket.AF_UNIX)

    # ... register methods to the server
    # Run the server
    srv.serve_forever()
except KeyboardInterrupt:
    # Shutdown the server gracefully
    srv.shutdown()
    srv.server_close()
finally:
    # You should clean up after the server stopped
    os.remove(socket_name)
```

This feature is tested on Linux during GitHub CI builds. It also has
been tested on Windows Subsystem for Linux (WSL) on Windows 10 1809.

This feature is not available on "pure" Windows, as it doesn't provide
the `AF_UNIX` address family.
