Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Well, I've been through the perldoc and it seems to mostly focus on the normal forking server model. Having a separate process for every client is all well and nice for most things but I have a slightly different situation.

Imagine you are building a simple chat. A thousand users connecting with telnet or something primitive like that. Everything one client sends is bounced back to all connected clients. In this case, is it really a good idea to have a separate process for every client? I can't help but think it would be easier to have one single process with a list of sockets. That way you could read from all clients in turn (non-blocking) and in the case of finding a message waiting, simply print it to all the sockets.

This does however give me a problem. In order to connect new clients I must do an accept() every now and then. That is blocking - which is bad in this cas since it will block the only process until someone connects.

So, am I barking up the wrong tree here? How would you people solve something like this? Will I be forced to muck about with threads, having one that looks for clients and one that does the chatting?

-- Curious

Replies are listed 'Best First'.
•Re: Non-forking server?
by merlyn (Sage) on Mar 24, 2003 at 17:17 UTC
Re: Non-forking server?
by Thelonius (Priest) on Mar 24, 2003 at 17:10 UTC
    You just include the listening socket in your select() or IO::Select and only call accept on it when there is activity on it (can_read if you are using IO::Select). That way you won't block.

    Updated: If you are using Perl 5.8, be aware that any socket call might return EINTR, which just means you should call it again. This wasn't true in earlier versions of Perl and is not covered in most examples/documentation. See 244415 for a little more info.

Re: Non-forking server?
by traveler (Parson) on Mar 24, 2003 at 17:14 UTC
    IO::Select has an example showing almost exactly what you want to do.

    HTH, --traveler

Re: Non-forking server?
by Anonymous Monk on Mar 24, 2003 at 17:44 UTC
    Another module you could consider is Net::Server::Multiplex.
    Net::Server will also simplify may other tasks you are likely to need.
    -Nathan
Re: Non-forking server?
by pg (Canon) on Mar 24, 2003 at 19:56 UTC
    As usual, I come to speak for threads ;-), so if you are using Perl 5.8, go threads.

    Just to create two threads:
    1. One to accept connections, so the accept() won't stop ongoing chatings.
    2. One to polling sockets thru IO::Select, see whether you get any incoming msgs for dispatching, and dispatch them.
    It might also be a good idea to have a third thread to dispatch msgs (instead of having the second thread doing both receiving and dispatching. This depends on your overall architecture, and msg format)