SourceForge pages | libsrv 1.0.2 release | SRVproxy 1.0 release
libsrv library helps to create network connections.
The two main design criteria were:
On this page:
A simple demo that is provided with the library is the
hello protocol. The client sends a person's name to the server, which sends back a greating using the name of the person who started the server. This self-invented hello protocol is not named anywhere in
/etc/services, but SRV records in DNS are used to locate the server name and port (as well as the redundancy scenario).
The client connects to the hello server under a particular domain. For example, if the server runs under
vanrein.org, it invokes
int sox = insrv_client ("hello", "tcp", "vanrein.org", NULL, 0, NULL);which returns a connected socket in the
soxvariable, when this is non-negative. If it is negative, it holds a negated value from
errno.hto indicate that the client could not be started.
Under water, the library tries to lookup the SRV record for the protocol, which you can replay as follows:
bash$ dig _hello._tcp.vanrein.org srv _hello._tcp.vanrein.org. 12H IN SRV 0 0 4128 phantom.vanrein.org.Which tells us that the service is running on
4128. The zeroes are for load balancing and backup service; since these are not defined and since there is only one SRV record,
libsrvhas only one hostname to try.
Would there have been no SRV record for this service, then
libsrv would have tried to contact the hostnames
hello.vanrein.org, in that order. The port to contact is in that case looked up from
The remainder of the programming effort is the protocol itself. Good luck, you're on your own now.
The server side of a protocol is usually more complicated because it should handle multiple clients. And because it must be configured with addresses to service on, with ports, etc. But not with
A process that is willing to accept connections for the
vanrein.org can be started in a similar way as the client:
int sox = insrv_server ("hello", "tcp", "vanrein.org", NULL, 0, NULL);The returned value is
sox(when non-negative) is a socket over which a client is connected. The
fork()mechanism is used to return many times from this one function call, once for every connection accepted. This means that the server is not good for high-traffic applications, but for smaller applications this is fine.
The server looks up the same SRV records as the client, and tries to bind to all the ports it finds, until one matches. If multiple ports and/or multiple IP addresses should be bound on the same computer, you would have to start the server more than once.
Along with the release of libsrv 1.0, there is also a release of SRVproxy 1.0, which is an SRV-aware HTTP-proxy. It functions really well, and using libsrv made it a really simple thing to write -- it took me only two hours to develop a working 1.0 release!
This proxy is intended for small-scale use (installed on localhost, for example). It receives normal web proxy lookups and relays them to a server that is found with SRV records if they exist, or with A/CNAME records otherwise. In both cases, the proxy is useful, because it will try all IP numbers it can find, not just the first one. If the domain name is given, but a prefix
www is needed, then the proxy discovers it.
If libsrv cannot connect, then nothing can.
If SRVproxy cannot find a web page, then nothing can.
libsrv is extremely simple, and many problems caused by sockets are out of your way. Connection-making is extremely reliable because it tries SRV records as well as plain A/CNAME records, and because it actually tries all IP numbers for a given server name. But the simplicity does come at a price.
libsrv library is not suitable for heavy-load servers; it is more suitable for integration in networking clients, and in light-load servers.
That is mainly because it forks off a new process for every connection accepted.
libsrv library does no caching of anything. Not of previously looked up DNS records (your resolver might cache this, however), not of previously failing servers, and most certainly not of connection data.
librv library does not support asynchronous DNS queries, which would allow for somewhat quicker solutions. Perhaps the future might change this. If this is a problem for you, do share that with the developers.
TODO: how about multiple client/server processes? Would that be okay?
For all situations where the above leads to problems, please checkout RULI and librascal. In return for a more complicated API, you will receive more control and more flexibilty. Do not expect
libsrv to take that road. In comparison,
libsrv is lean and mean, whereas
RULI is heavy and savvy.
This project evolved from FingerHosting, which in turn grew out of my SRV record involvement.
And of course, this project is hosted on ever-wonderful SourceForge!