# RPyC Servers

Since RPyC is a symmetric protocol (where both client and server can process requests), an [RPyC server](../api/utils_server.md) is a largely just a main-loop that accepts incoming connections and calls `serve_all`. RPyC comes with three built-in servers:

- Forking - forks a child-process to handle each incoming connection (POSIX only)
- Threaded - spawns a thread to handle each incoming connection (POSIX and Windows)
- Thread Pool - assigns a worker-thread for each incoming connection from the thread pool; if the thread pool is exhausted, the connection is dropped.

If you wish to implement new servers (say, reactor-based, etc.), you can derive from `rpyc.utils.server.Server` and implement `_accept_method()` to your own liking.

> [!NOTE]
> RPyC uses the notion of *authenticators* to authenticate incoming connections. An authenticator object can be passed to the server instance upon construction, and it is used to validate incoming connections. See [Authenticators](../api/utils_authenticators.md) for more info.

## Classic Server

RPyC comes "bundled" with a [Classic](classic.md)-mode server -- `rpyc_classic.py`. This executable script takes several command-line switches and starts an RPyC server exposing the `ClassicService`. It is installed to your python's `scripts/` directory, and should be executable from the command line. Example usage:

    $ ./rpyc_classic.py -m threaded -p 12333
    INFO:SLAVE/12333:server started on [0.0.0.0]:12333
    INFO:SLAVE/12333:accepted 127.0.0.1:34044
    INFO:SLAVE/12333:welcome [127.0.0.1]:34044
    INFO:SLAVE/12333:goodbye [127.0.0.1]:34044
    ^C
    WARNING:SLAVE/12333:keyboard interrupt!
    INFO:SLAVE/12333:server has terminated
    INFO:SLAVE/12333:listener closed

The classic server takes the following command-line switches (try running it with `-h` for more info):

### General switches

- `-m`, `--mode=MODE` - the serving mode (`threaded`, `forking`, or `stdio`). The default is `threaded`; `stdio` is useful for integration with inetd.
- `-p`, `--port=PORT` - the TCP port (only useful for `threaded` or `forking` modes). The default is `18812`; for SSL the default is `18821`.
- `--host=HOSTNAME` - the host to bind to. The default is `0.0.0.0`.
- `--ipv6` - if given, binds an IPv6 socket. Otherwise, binds an IPv4 socket (the default).
- `--logfile=FILENAME` - the log file to use. The default is `stderr`
- `-q`, `--quiet` - if given, sets quiet mode (no logging).

### Registry switches

- `--register` - if given, the server will attempt to register with a registry server. By default, the server will **not** attempt to register.

The following switches are only relevant in conjunction with `--register`:

- `--registry-type=REGTYPE` - The registry type (`UDP` or `TCP`). The default is `UDP`, where the server sends timely UDP broadcasts, aimed at the registry server.
- `--registry-port=REGPORT` - The TCP/UDP port of the registry server. The default is `18811`.
- `--registry-host=REGHOST` - The host running the registry server. For UDP the default is broadcast (`255.255.255.255`); for TCP, this parameter is **required**.

### SSL switches

If any of the following switches is given, the server uses the SSL authenticator. These cannot be used with conjunction with `--vdb`.

- `--ssl-keyfile=FILENAME` - the server's SSL key-file. Required for SSL
- `--ssl-certfile=FILENAME` - the server's SSL certificate file. Required for SSL
- `--ssl-cafile=FILENAME` - the certificate authority chain file. This switch is optional; if it's given, it enables client-side authentication.

## Custom RPyC Servers

Starting an RPyC server that exposes your service is quite easy -- when you construct the `rpyc.utils.server.Server` instance, pass it your `rpyc.core.service.Service` factory. You can use the following snippet:

    import rpyc
    from rpyc.utils.server import ThreadedServer # or ForkingServer

    class MyService(rpyc.Service):
        #
        # ... you service's implementation
        #
        pass

    if __name__ == "__main__":
        server = ThreadedServer(MyService, port = 12345)
        server.start()

Refer to `rpyc.utils.server.Server` for the list all possible arguments.

## Registry Server

RPyC comes with a simple command-line registry server, which can be configured quite extensively by command-line switches. The registry server is a bonjour-like agent, with which services may register and clients may perform queries. For instance, if you start an RPyC server that provides service `Foo` on `myhost:17777`, you can register that server with the registry server, which would allow clients to later query for the servers that expose that service (and get back a list of TCP endpoints). Example usage:

    $ ./bin/rpyc_registry.py --listing
    DEBUG:REGSRV/UDP/18811:registering 172.18.0.6:18861 as MY

    For more info, see [api-registry](../api/utils_registry.md).

### Switches

- `-m`, `--mode=MODE` - The registry mode; either `UDP` or `TCP`. The default is `UDP`.
- `-p`, `--port=PORT` - The UDP/TCP port to bind to. The default is `18811`.
- `-f`, `--file=FILE` - The log file to use. The default is `stderr`.
- `-q`, `--quiet` - If given, sets quiet mode (only errors are logged)
- `-t`, `--timeout=PRUNING_TIMEOUT` - Sets a custom pruning timeout, in seconds. The pruning time is the amount of time the registry server will keep a previously-registered service, when it no longer sends timely keepalives. The default is 4 minutes (240 seconds).
- `-l`, `--listing` - Give a boolean indicating if registry should allow sending the list of its known services. The default is False.
