Re: C sockets

From: Walter Roberson (roberson_at_ibd.nrc-cnrc.gc.ca)
Date: 03/11/05


Date: 11 Mar 2005 07:52:25 GMT

In article <1d55641b.0503102236.70a60a95@posting.google.com>,
kernel.lover <cranium.2003@gmail.com> wrote:
: i want to know to have multiple clients connects to same server
:program does following is correct code

Sockets aren't part of the C standard, so most people would
refer you to comp.unix.programming or a similar newsgroup.

: if(fork() == 0) {

: }

: else {
: close(client_sockfd);
: }

That code is not correct: after a time it will stop accepting
connections. That's because the parent never does a wait()
or waitpid() or wait3() to collect the status of the dead children,
so the dead children are going to linger on and pile up until
some resource is exhausted.

:If yes then when to use then select call(i.e. FD_SET,FD_CLR,FD_SET)?
:if no then select is only thing to have server socket program on one
:pc and other clients on many pcs to have communication with server?
: I want to have communication environment with many clients and one
:server serving all at same time.

There is more than one "correct" way.

select() is useful when you want to perform asynchronous action,
or want to put a time limit on how long you will wait for input.

An example of where you would want select() is in a case
where you have a routine which you are receiving data from
a pipe but are also in communication with the user: you don't
know which of the two input sources is going to be ready first,
so you use select() to tell you as soon as the first of them is
ready.

When you fork() a new process to handle each client, then you need to
be aware that -logically- speaking, an entire copy of the parent
process and all of its variables is created, so -logically- speaking
serving N clients requires at least (N+1) times the amount of memory
that the master process takes. Most modern unix systems optimize the
actual memory usage by using tricks such as "copy on write" (which
divides the memory into "pages" and shares copies of the page until one
process writes to the page, at which point that process is given an
unshared copy of the page.) That's something that is implimentation-
specific, though, and may depend upon your current kernel settings and
current resource limits: in some systems, the OS will want to reserve
enough real memory to make a complete copy of the parent process, even
though it doesn't know that the parent process will need the memory.
The theory there is that if the complete memory is reserved at the time
of the fork, then if the fork successed you know that you will be able
to write to all the existing variables, whereas in systems which do
"copy on write" and do not reserve all the memory ahead of time, you
run the risk of running out of memory and crashing the process part way
through, even though you thought you were just writing to a location
that is "known" to exist [because the write triggered the copy and
there wasn't enough room for the new page.]

If you do not fork() and instead handle everything in one
process, then that one process has to keep track of all the state
for all of the processes; keeping everything straight could
complicate the code a fair bit. Also, if you use only a single
process then unless you can take advantage of "threads" then
that one process has to do all the computation work -- and
while it is doing computation work, it is busy and cannot be
doing computation work on behalf of a different socket,
nor can it be doing socket I/O while it is busy computing.
The response times might become unacceptable, whereas the
fork() case might be able to run the forked process on a
different CPU (if you have a multi-cpu machine.)

Also, if you take the approach of doing everything in one process, then
if you get busy enough, you are going to run out of available socket
descriptors. If you are using FILE* I/O for each socket then you could
run out in as little as 100 or 255 active sockets. 100 used to be a
common implimentation limit; 255 arises out of the common use of a
single character to hold the underlying descriptor number. The way of
finding out how many files you can open is to ask to
sysconf(_SC_OPEN_MAX) -- note that sysconf() is a POSIX routine,
not a C library routine.

-- 
'ignorandus (Latin): "deserving not to be known"'
   -- Journal of Self-Referentialism


Relevant Pages

  • RE: CONFIG_DEBUG_SLAB_LEAK omits size-4096 and larger?
    ... of memory, ... Remind me what the most recent *bad* kernel was of those you tested? ... run a check under full load (800 + clients). ... So with that many clients all making requests to the server at once, ...
    (Linux-Kernel)
  • RE: Exchange 2003 and timeout errors on XP machines
    ... lose of connectivity on the server but only error 26 on the clients and then ... I will reboot the server and see what ... After replacing 1 client computer's network cable, ... > Store.exe will take as much memory as possible to provide better service ...
    (microsoft.public.windows.server.sbs)
  • [Full-Disclosure] Broadcast crash in Xpand Rally 1.0.0.0
    ... versus server and clients ... The problem is caused by an unchecked memory allocation controlled by ... If the memory to allocate is too big the mallocfunction will fail ...
    (Full-Disclosure)
  • Broadcast crash in Xpand Rally 1.0.0.0
    ... versus server and clients ... The problem is caused by an unchecked memory allocation controlled by ... If the memory to allocate is too big the mallocfunction will fail ...
    (Bugtraq)
  • Broadcast crash in Xpand Rally 1.0.0.0
    ... versus server and clients ... The problem is caused by an unchecked memory allocation controlled by ... If the memory to allocate is too big the mallocfunction will fail ...
    (Full-Disclosure)

Loading