![]()
|
Programming with Rudiments using the Base Classes
Here is some sample code for a daemon process that writes "hello" every 2 seconds. Most daemons don't write anything to the console, but this one does for purposes of demonstration. #include <rudiments/daemonprocess.h> #include <iostream.h> #include <unistd.h> #include <stdlib.h> class mydaemon: public daemonprocess { public: void init(); void loop(); }; void mydaemon::init() { runAsUser("nobody"); runAsGroup("nobody"); detach(); } void mydaemon::loop() { for (;;) { cout << "hello" << endl; sleep(2); } } mydaemon *md; void shutDown() { delete md; exit(0); } main() { md=new mydaemon; md->handleShutDown((void *)shutDown); md->init(); md->loop(); }Using the Server Socket Class Daemons are commonly used to serve data to clients over a network. Below is an example combining the daemon and serversocketpool classes. This server receives a string from the client and writes the same string back to the client. #include <rudiments/daemonprocess.h> #include <rudiments/serversocketpool.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> class myserver: public daemonprocess, public serversocketpool { public: myserver(); ~myserver(); void loop(); void session(); private: serversocket inetsocket; serversocket unixsocket; genericsocket *clientsocket; }; myserver::myserver() : daemonprocess(), serversocketpool() { // run as a different user/group runAsUser("nobody"); runAsGroup("nobody"); // detach from the controlling tty detach(); // open, bind and listen on an inet port and unix socket inetsocket.listenOnInetPort(8040,15); unixsocket.listenOnUnixPort("/tmp/mysocket",S_IRUSR|S_IWUSR,15); // add the sockets to the pool addSocket(&inetsocket); addSocket(&unixsocket); } myserver::~myserver() { inetsocket.closeSocket(); unixsocket.closeSocket(); } void myserver::loop() { for (;;) { // accept connections, with no timeout serversocket *whichsocket; waitForClientConnection(-1,-1,&whichsocket,&clientsocket); // fork to handle the new connection if (!fork()) { // close the duplicated server socket, // engage in a session with the client, // close the client socket and exit whichsocket->stopListening(); session(); clientsocket->closeSocket(); _exit(0); } // close the client socket, but leave the server // socket open to accept more connections clientsocket->closeSocket(); } } void myserver::session() { // read a string from the client short bytes; readData(&bytes); char *string=new char[bytes+1]; readData(string,bytes); // write the same string back to the client writeData(bytes); writeData(string,bytes); // clean up delete[] string; } myserver *ms; void shutDown() { delete ms; exit(0); } main() { ms=new myserver(); ms->handleShutDown((void *)shutDown); ms->loop(); } Notice that this server listens on both inet and unix ports. Inet ports allow clients and servers to talk across a network. Unix ports allow clients and servers on the same machine to talk through a pipe. Though clients and servers on the same machine could talk over inet ports, unix ports are much faster and use fewer system resources. Using the Client Socket ClassHere's the code for a client that can talk to the server above. This client sends a string to the server, reads what the server sends back and prints it out. It does this once over an inet port and once over a unix port. #include <rudiments/clientsocket.h> #include <iostream.h> class myclient: public clientsocket { public: void inetSession(char *host, int port, char *message); void unixSession(char *socket, char *message); private: void session(char *message); }; void myclient::inetSession(char *host, int port, char *message) { connectToServer(host,port,0,1); session(message); } void myclient::unixSession(char *socket, char *message) { connectToServer(socket,0,1); session(message); } void myclient::session(char *message) { // write a message to the server writeData((short)strlen(message)); writeData(message); // read a message back from the server short bytes; readData(&bytes); char *string=new char[bytes+1]; readData(string,bytes); // write out the message we got from the server cout << string << endl; // clean up delete[] string; } main() { // declare an instance of our client myclient mc; // connect to a known inet host/port and unix socket and // send a message over each connection mc.inetSession("localhost",8040,"message over inet port"); mc.unixSession("/tmp/mysocket","message over unix port"); }Using the Complex Socket Initialization methods of the Server Class Setting up a server to listen on a socket is actually a multi-step process. The listenOnInetPort(), listenOnUnixPort() and listenOnPorts() methods simplify this process but some applications may require a more flexible interface. If you need to set socket options or perform additional actions between the steps of socket initialization, you can use the Complex Socket Inititalization methods of the server class. Below is an alternative implementation of the myserver constructor in which some socket options are set. myserver::myserver() : daemonprocess(), serversocketpool() { // run as a different user/group runAsUser("nobody"); runAsGroup("nobody"); // detach from the controlling tty detach(); // initialize the ports inetsocket.initInetPort(8040); unixsocket.initUnixPort("/tmp/mysocket",S_IRUSR|S_IWUSR,15); // set some socket options inetsocket.lingerOnClose(10); inetsocket.reuseAddresses(); unixsocket.lingerOnClose(10); // bind to the ports inetsocket.bindSocket(); unixsocket.bindSocket(); // listen on the ports inetsocket.listenForClientConnection(15); unixsocket.listenForClientConnection(15); // add sockets to the pool addSocket(&inetsocket); addSocket(&unixsocket); } |