======= Servers ======= .. note:: If your goal is to write IOCs, see :doc:`iocs`. Caproto includes three implementations of a Channel Access server for three different Python concurrency libraries: * asyncio (built in to Python, as part of its standard library) * curio * trio To learn more about concurrency in Python (and in general) we recommend these introductory resources, suggested by a caproto user: * `Speed up your Python program with concurrency `_ * `Async IO in Python: A Complete Walkthrough `_ Core API -------- The core IOC code abstracts out the particular server implementation, so IOC authors do not need to interact with the server API directly. The core server API remains a work-in-progress and is subject to change, though as of 2021 it is likely mostly stable. See more details in :doc:`server_api`. Writing your own IOCs --------------------- There is an entire chapter in this documentation dedicated to EPICS IOCs and the related tools we have. Take a look at :doc:`iocs` for more information. Running multiple servers on one host ------------------------------------ For service discovery EPICS primarily relies on UDP broadcast (rsrv also supports multicast, this is not (yet) supported by caproto). To achieve this all of the servers processes on a host bind the canonical port (default 5064) with the ``SO_REUSEADDR`` and ``SO_REUSEPORT`` settings. These settings allow multiple sockets (across different processes or threads) to bind the same interface and port, `see this SO post `_ for more details. When configured this way the UDP sockets: * load balance between IOC processes for uni-cast messages (the exact method of load balancing changed with the 3.9 Linux kernel) * sent to all IOC processes for broadcast messages Because you `can not broadcast to 127.0.0.1 `__ if you bind your IOCs to the localhost interface you will be able to talk to at most 1 of them from any given client. If you want to put non-broadcast IPs in ``EPICS_CA_ADDR_LIST`` then you can not run more than one IOC per host (because search requests will be load balanced). If you have a host with more than one interface and you want to bind your IOCs to a specific interface doing so by specifying the broadcast address will work, however in that case any uni-cast searches (ex a specific IP in tho ``EPICS_CA_ADDR_LIST`` will be ignored). Binding to the specific interface using the ip adderesss will result in the messages to the broadcast address being ignored and uni-cast messages being load-balanced. The EPICS wiki `has some additional details about how to set up iptables `__ to work around this issue.