Re: Approaches to serve multiple clients
Re: Approaches to serve multiple clients
- Subject: Re: Approaches to serve multiple clients
- From: Igor Garnov <email@hidden>
- Date: Mon, 20 Dec 2004 00:18:35 +0300
Thanks very much for the answer!
On 19/12/2004, at 10:02 AM, Igor Garnov wrote:
I am going to write a daemon, which is supposed to serve many clients.
What kind of server are you writing?
This is supposed to be a daemon to serve game clients. Although the
nature of the game assumes that there won't be much traffic among
clients, I'm also thinking of implementing a feature that would enable
clients to talk to each other during games. As I understand,
transferring audio data will add a lot of traffic unless I use extreme
compression before actual dispatching of data to the server. I am not
sure if it's worth it.
They will connect and probably stay connected for a long time
(several hours). They will exchange data between themselves.
As I understand, there are two main approaches to organize the
workflow:
Actually, there are more, see below...
1) I can fork with each connecting client, and serve each client by a
separate process. Of course, this is easy from the network
programmer's point of view, but taking into account the problem of
transferring data from a client to a client, this also has some
disadvantages. Moreover, this frightens me a little, because if there
are, say, 1000 clients, there also are 1000 processes. This is no
problem for Apache, because the lifetime of each its process is very
short, but what about my situation? Is it OK to have 1000 processes
at the same time? What if there are 2000? 3000?
There are a significant number of times where using fork() is a good
thing. Many (?) OS's (such as Linux, I have no idea about Mac OS
X/FreeBSD etc) implement fork() in a manner that is very efficient
(ie, the memory requirements scale at less than O(N). One such
technique is Copy-on-Write, which is what Linux uses.
One thing you need to consider is if the server's children will need
to communicate or share data structures amongst themselves. Since
fork() provides no IPC mechanism, you would need to use some other IPC
mechanism, or use select() or threads instead.
I am really not experienced with Unix network programming, whereas I
have some experience on Windows. But I remember reading somewhere that
on most flavors of Unix there is no big difference between creating a
thread and a process from the OS's point of view, which makes it
pointless tempering with threads when there are much more convenient
entities as processes.
As I see, threads would be more convenient to me because they live in
the same address space, which makes it relatively easy to exchange data
between clients.
Another (very important, IMHO) thing to consider is that using fork()
protects you from DoS attacks (whereby crashing the server-child
process doesn't crash the rest of the server handlers, as would be the
case with select or threads). However, with fork(), you may run come
up against the limit of processes you are allowed, and opens up a
partial DoS if you don't manage the number of connections at one time.
Also on the point of security, with select(), it opens up a risk
similar to cross-site-scripting, whereby if there is a vulnerability
where an attacker can write to a shared data-structure, other clients
accessing that data-structure could also be affected.
2) I can use 'select' and have all clients served in the same
process. But as far as I know, there is a limit on the number of
sockets that 'select' can watch upon.
Yes, I think POSIX guarantees at least 1024, but I could be wrong.
FD_SETSIZE is 1024 on Mac OS X, and 1024 on Linux also. If this is an
issue, you're probably going to bumping into other limits as well,
most notably the number of open files.
I don't think I'm going to use files extensively, but this of course
should also be taken into account... Thanks!
Having written this, I personally think that I should fork a process
for each 100 clients, and use 'select' in this process to catch
network events.
This is the best way to start at least.
But this approach adds complexity to the methods used to ensure
communication between clients.
I would be really grateful for any ideas on the problem.
I can't give you any more advice until I figure out what exactly is it
that you're designing.
I will say, however, that you should get your hands on a copy of Unix
Network Programming, volume 1. This has all the information you need
about writing Socket based programs, including design issues.
Well, I have it, and it is this book where I've read about 'select'
limitations. Moreover, it's in this book the conclusion is made, that
with RARE exclusions it's best to fork a new process for a new client
instead of trying to serve them all with 'select' or playing with
threads.
But, as I have already written, it's normal for Apache to fork for
every client and every page served, because every such process lives
only for a second. But is this approach also normal for daemon whose
clients will probably stay connected for at least an hour?
Regards,
Igor
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden