Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Nov 1996 12:38:09 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        stesin@gu.net (Andrew Stesin)
Cc:        hackers@freebsd.org, squid-users@nlanr.net
Subject:   Re: Programming technique for non-forking servers?
Message-ID:  <199611131938.MAA22676@phaeton.artisoft.com>
In-Reply-To: <Pine.BSI.3.95.961113122121.8648B-100000@creator.gu.kiev.ua> from "Andrew Stesin" at Nov 13, 96 12:32:33 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> can anyone point me to some book, or URL(s), where the
> programming technique for writing non-forking network server
> daemons is described in details? with caveats, non-obvious
> places...

The Stevens books cover it...


> Yes, there are sources, but I'd really like to read
> some general theory on the subject.

The general theory is that you change a blocking call into a non-blocking
call + a context switch.

In other words, it's state-machine based event driven multithreading.


 ,------> wait for packet
 |              |
 |              v
 |     select() o-----------------------.
 |              | socket A              | socket B
 |              v                       v
 |              f(context A)            f(context B)
 |               \                     /
 |                 \                /
 |                   \           /
 |                     \      /
 |                       \ /
 |                        v
 |                        o packet processing function f()
 |                        |
 |                        v
 |                        o any additional processing
 |                        |
 `------------------------'

In addition, the packet may be a connect() request from a remote client;
if so, you need to:

1)	accept the connection to bind it to a local socket
2)	add the socket to the list of fd's that the select is
	listening to
3)	continue processing


so the main loop looks like:

	/*
	 * init
	 */
	create connect_socket for incoming connections
	post listen() on socket connect_socket
	init default fd_set default_read_mask to contain connect_socket
	set max_fd to connect_socket + 1
	initialize context_list to NULL

	/*
	 * main loop
	 */
	while( 1) {
		copy default_read_mask to real_read_mask
		select( max_fd, real_read_mask)
		/*
		 * if we got here, a socket event has occurred;
		 * real_read_mask will now contain  the fd's
		 * (sockets) which you must do processing on.
		 */

		/* check for incoming connections, first thing*/
		if( FD_ISSET( connect_socket, &real_read_mask)) {
			/* clear so we don't hit it in processing loop*/
			FD_CLR( connect_socket, &real_read_mask)

			/* generate default context for new connection*/
			ctxp = new_context();
			add_context( ctxp, context_list);
			ctxp->state = 0;
			ctxp->fd = accept( connect_socket)

			/* accept events on this context*/
			FD_SET(ctxp->fd, &default_read_mask)
		}

		/* process all contexts which aren't incoming connections*/
		for( ctxp = context_list; ctxp = ctxp->next) {
			if( FD_ISSET( ctxp->fd, &real_read_mask)) {
				handle_event( ctxp);
			}
		}
	}


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199611131938.MAA22676>