libsrv -- Simply making network connections flaw-less


SourceForge pages  |  libsrv 1.0.2 release  |  SRVproxy 1.0 release

The libsrv library helps to create network connections. The two main design criteria were:

On this page:

An simple example client

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 sox variable, when this is non-negative. If it is negative, it holds a negated value from errno.h to 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 phantom.vanrein.org port 4128. The zeroes are for load balancing and backup service; since these are not defined and since there is only one SRV record, libsrv has only one hostname to try.

Would there have been no SRV record for this service, then libsrv would have tried to contact the hostnames vanrein.org and hello.vanrein.org, in that order. The port to contact is in that case looked up from /etc/services.

The remainder of the programming effort is the protocol itself. Good luck, you're on your own now.

An simple example server

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 libsrv!

A process that is willing to accept connections for the hello under 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.

A realistic application of libsrv

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.

Limitations of libsrv (and the big brother that solves them)

Programming with 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.

The 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.

The 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.

The 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.

Thank you notes

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!
SourceForge Logo