hi dido, i cc plug so that others can benefit and learn how to write a high performance and scalable client-server design that you are trying to achieve... see my solution below....
On Mon, Mar 23, 2009 at 1:17 PM, Rafael Sevilla <[email protected]> wrote: > I've lately been doing research in event-driven network servers, and > these are by nature single-threaded. There is, of course, a natural > way to extend such servers to being multithreaded. We'd have a single > thread whose pm;u job is to listen on the network port and accept(2) > socket connections going to the port it is listening on. Instead of > doing I/O on the socket directly, by adding it to the list of file > descriptors select(2) or epoll(7) would listen to, it chooses a worker > thread and sends the accepted socket to it, which then adds it to its > polled file descriptors, performing all relevant I/O with the client. > > The only problem with this is how the acceptor and worker threads could > communicate in a non-blocking fashion. The usual IPC primitives could > be used to do this, as they are very efficient. However, for this to be > practical there would have to be something like a super-select or poll > call that could wait on a set of file descriptors as well as on > semaphores or message queues, returning when either I/O is possible on > any of the registered file desriptors or if the semaphore may be waited > on (or the message queue may be read) without blocking. This would be > preferable, but it seems there's no POSIX system call that does what is > required. Another way would be to use pipes to perform communication > between the acceptor and worker threads, but that seems less efficient > than direct semaphore/message queue use. If it's possible to make the > system send a signal when a semaphore or message queue is available for > nonblocking use, that could be another way (is there?). > > What other ideas for making a hybrid evented-threaded server have you > guys heard of? your client-server architectural design is a prethreaded server with main thread accept(2).. there is another one technique called prethreaded server with per-thread accept(2).. the latter is more advance than the former but ill focus the discussion to your problem... you have the main thread as acceptor for a given listening port and distributes the accepted filedescriptor after the connection established to your threaded servers doing a select(2) or epoll(7) for i/o multiplexing... since your threaded servers are doing i/o multiplexing and in the event that there are no i/o taking place... your threaded servers are in blocking state... when a connection comes accepted by acceptor... your problem is how can you send the accepted filedescriptor to a threaded server that is in blocking state? the answer is inter-process communication... in your threaded server.. either you are using select(2) or epoll(7) function... the parameters of those two functions are based on the socket filedescriptor that your acceptor passed on... take note that select(2) or epoll(7) is not only limited to socket filedescriptor.. it can accept any filedescriptors such as pipe filedescriptor, fifo filedescriptor and other filedescriptors... since select(2) or epoll(7) use any filedescriptor.. the trick for your inter-process communicaton problem is to use pipe(2)... when creating a pipe.. it return two filedescriptors.. one for reading and one for writing... by default... pipe's reading filedescriptor is in blocking state... the solution goes like this... 1. define N as the number of your prethreaded servers 2. create N pipes.. you now have N pairs of read and write pipe filedescriptors 3. each read pipe filedescriptor is assigned and the first filedescriptor of your threaded server select(2) or epoll(7) function... while the N write pipes are kept by your acceptor for referencing to a particular threaded server for distribution... your referencing can be round-robin, least connection or other load balancing algorithm you want to implement... 4. after a connection established.. your acceptor received a socket filesdesciptor... send or write that socket filedescriptor *value* to a particular write pipe.. and let the corresponding read pipe of a particular threaded server read that socket filedescriptor value... 5. after reading and have that socket filedescriptor value inside your threaded server.. your threaded server add that value to select(2) or poll(2) to anydescriptor sets... your descriptor set now contained read pipe filedescriptor and the newly accepted socket filedescriptor.. thats it.. you have now a working high performance and scalable client-server design and have fun with your network programming... fooler. _________________________________________________ Philippine Linux Users' Group (PLUG) Mailing List http://lists.linux.org.ph/mailman/listinfo/plug Searchable Archives: http://archives.free.net.ph

