C sockets

K

kernel.lover

Hello,
i want to know to have multiple clients connects to same server
program does following is correct code
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>

int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address,
server_len);

/* Create a connection queue, ignore child exit details and wait for
clients. */

listen(server_sockfd, 5);

signal(SIGCHLD, SIG_IGN);

while(1) {
char ch;

printf("server waiting\n");

/* Accept connection. */

client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);

/* Fork to create a process for this client and perform a test to see
whether we're the parent or the child. */

if(fork() == 0) {

/* If we're the child, we can now read/write to the client on
client_sockfd.
The five second delay is just for this demonstration. */

read(client_sockfd, &ch, 1);
sleep(5);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
exit(0);
}

/* Otherwise, we must be the parent and our work for this client is
finished. */

else {
close(client_sockfd);
}
}
}

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.
 
J

Jens.Toerring

kernel.lover said:
i want to know to have multiple clients connects to same server
program does following is correct code

<code snipped>

And with this you're in the wrong group. The C language does _not_
have any built-in support for network operations, nor are the read()
and write() or fork() functions or nearly everything else you're
using in that program of yours standard C functions. The only func-
tions you use that are standard C functions are main(), printf() and
exit() (not counting sizeof() since it's not a fucntion), all of the
rest are system-specific extensions. So please take that to a news-
group that deals with the details of the system you are using, which
in your case seems to some kind of UNIX, so 'comp.unix.programmer'
would seem to be the most appropriate.

Regards, Jens
 
W

Walter Roberson

: 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.
 
J

Jens.Toerring

Walter Roberson said:
: 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.

And that for a good reason since there are the people that
will take care of correcting any mistakes made in replies.
So, if you can't refrain from answering here at least set
follow-ups appropriately.

: 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.

And just to avoid that there's a call of

signal(SIGCHLD, SIG_IGN);

before the fork() which you snipped - that setting prevents the
creation of zombies, at least assuming the OP is using UNIX. Do
I need to say more in favor of keeping things in the proper
newsgroups?
Regards, Jens
 
K

Keith Thompson

: 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.

And with good reason. You're not doing the OP a favor by attempting
to answer his question here. I know I make mistakes fairly regularly,
so I try to post in newsgroups where they can be corrected.

The folks in comp.unix.programmer know all about fork(), sockets, and
so forth, and they can provide far better and more reliable
information than we can here. Some of the comp.lang.c regulars are
undoubtedly Unix experts, but we can't match the level of expertise
you'll find in an appropriate newsgroup, and it would be inappropriate
for us to try.

I'm not implying that your response is wrong. As far as I know, your
response could be entirely correct (I lack the expertise to make that
judgement).
 
J

jacob navia

Keith said:
And with good reason. You're not doing the OP a favor by attempting
to answer his question here. I know I make mistakes fairly regularly,
so I try to post in newsgroups where they can be corrected.

The folks in comp.unix.programmer know all about fork(), sockets, and
so forth, and they can provide far better and more reliable
information than we can here. Some of the comp.lang.c regulars are
undoubtedly Unix experts, but we can't match the level of expertise
you'll find in an appropriate newsgroup, and it would be inappropriate
for us to try.

I'm not implying that your response is wrong. As far as I know, your
response could be entirely correct (I lack the expertise to make that
judgement).

I would say the answers that people give here are
to be understood like this:

THIS ANSWERS ARE BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR C.L.C MAKE ANY
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE USABILITY
OF THIS ANSWERS OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.

Should we add this to the FAQ? :)
 
J

Jens.Toerring

I would say the answers that people give here are
to be understood like this:
THIS ANSWERS ARE BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR C.L.C MAKE ANY
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE USABILITY
OF THIS ANSWERS OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Should we add this to the FAQ? :)

No, that's clear anyway - I don't think I could sue you if I take
your advice and this results in my computer catching fire and the
house burning down. The question is about where's the best chance
of getting a correct and _checked_ answer. While I am sure you
know a lot about writing compilers it wouldn't be a good thing if
you answer questions about that topic here since there are only a
few people around that can correct you if necessary. But when you
answer in e.g. comp.compilers and make a mistake (as it can happen
to the best of us), then the chances are a lot bigger that someone
will point that out over there.
Regards, Jens
 
W

Walter Roberson

:And just to avoid that there's a call of

:signal(SIGCHLD, SIG_IGN);

:before the fork() which you snipped - that setting prevents the
:creation of zombies, at least assuming the OP is using UNIX.

On at least some Unix, to have that effect you need to
sigaction() with the SA_NOCLDWAIT flag.

Proper handling of SIGCHLD can be difficult when there are
multiple children -- SIGCHLD has special properties that
differ depending on the heritage of your Unix.
 
J

Jens.Toerring

Walter Roberson said:
:And just to avoid that there's a call of
:signal(SIGCHLD, SIG_IGN);
:before the fork() which you snipped - that setting prevents the
:creation of zombies, at least assuming the OP is using UNIX.
On at least some Unix, to have that effect you need to
sigaction() with the SA_NOCLDWAIT flag.

Well, I should have written "a POSIX compliant UNIX version"...
Proper handling of SIGCHLD can be difficult when there are
multiple children -- SIGCHLD has special properties that
differ depending on the heritage of your Unix.

I won't argue with that;-) But that's exactly why clc is the wrong
place for this and comp.unix.programmer is so much better suited.

Regards, Jens
 
W

Walter Roberson

|> 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,

|And just to avoid that there's a call of

|signal(SIGCHLD, SIG_IGN);

|before the fork() which you snipped - that setting prevents the
|creation of zombies, at least assuming the OP is using UNIX.

You have a citation for this that overrides IEEE 1003.1-1990
section 3.3.1.3 "Signal Actions" subsection (2) SIG_IGN, clause

(d) If a process sets the action for the SIGCHLD signal to
SIG_IGN, the behaviour is unspecified.

See also B.3.3.1.3 "Signal Actions", third sentance of the third
paragraph:

POSIX.1 requires this for the sake of consistancy and also for
completeness, since the only signal this applies to is SIGCHLD,
and POSIX.1 disallows setting its action to SIG_IGN.

Then there is 3.2.2.2, the description of _exit(), which
indicates in subsection (5) that support for the SIGCHLD signal
is optional.


:Do
:I need to say more in favor of keeping things in the proper
:newsgroups?

It appears to me that your correction of my statements were incorrect.

signal() did not exist in 4.3 BSD (which uses sigvec(), sigsetmask()),
and SIGCHLD did not exist in System V; thus the combination of
signal() with SIGCHLD is either a non-portable OS extension or else
an attempt to invoke POSIX.1 behaviour... with POSIX.1 varying from
prohibitting you from SIG_IGN a SIGCHLD to saying the behaviour
is unspecified (and thus completely OS versions specific.)

There is no standard POSIX behaviour that allows the creation of
zombies to be skipped; the most one can do is not have the parent
signalled under various conditions. That does not relieve the
parent of the responsibility of using wait() or equivilent. Indeed,
if you examine the SIG_DFL behaviour for SIGCHLD you will find that
processes ignore SIGCHLD by default -- SIGCHLD being generated
not just when a child exits but also when the child is SIGSTOP'd
(though that behaviour can be modified.)
 
K

Keith Thompson

:Do I need to say more in favor of keeping things in the proper
:newsgroups?

It appears to me that your correction of my statements were incorrect.

That's an equally strong argument in favor of keeping things in the
proper newsgroups. We're seeing a disagreement about how sockets
work; you say one thing, Jens says something else. This cannot be
effectively resolved in this newsgroup, because we lack the expertise.
It could be resolved in comp.unix.programmer, which is full of people
who know all about sockets.

Meanwhile, we're wasting our time here talking about sockets rather
than about C.

Please please take this discussion to comp.unix.programmer.
 
C

CBFalconer

Walter said:
.... snip ...

:Do
:I need to say more in favor of keeping things in the proper
:newsgroups?

It appears to me that your correction of my statements were incorrect.

signal() did not exist in 4.3 BSD (which uses sigvec(), sigsetmask()),
and SIGCHLD did not exist in System V; thus the combination of
signal() with SIGCHLD is either a non-portable OS extension or else
an attempt to invoke POSIX.1 behaviour... with POSIX.1 varying from
prohibitting you from SIG_IGN a SIGCHLD to saying the behaviour
is unspecified (and thus completely OS versions specific.)

You are simply proving his point. This discussion has no business
on c.l.c. IT IS OFF-TOPIC. Neither Posix nor sockets are
mentioned in the ISO C standard. You are still annoying with the
non-standard quote mark.
 
M

Mark McIntyre

|> 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,

|And just to avoid that there's a call of

|signal(SIGCHLD, SIG_IGN);

|before the fork() which you snipped - that setting prevents the
|creation of zombies, at least assuming the OP is using UNIX.

You have a citation for this that overrides IEEE 1003.1-1990
section 3.3.1.3 "Signal Actions" subsection (2) SIG_IGN, clause

etc.
Guys, this is horribly offtopic here. Please take it over to
comp.unix.programming.
 
W

Walter Roberson

:You are still annoying with the
:non-standard quote mark.

a) There is no standard quote mark.

b) I am not responsible for your running any particular newsreader that
does non-standard things to Usenet messages. If your reader chokes on
completely valid messages, then it is up to you to either live with it,
chuck it, fix it, or get someone to fix it for you. Don't be going around
demanding that people change perfectly conformant RFC 1036 postings
to suit the straight-jacket that you have voluntarily locked yourself into.

c) Most people do -not- use programs that automatically count '>' and
colourize. The quoting structure I use is easier for those people to
follow. You have taken a weak convention and proclaimed it as a virtue,
and are attempting to now fossilize the broken weak convention.
You want "bug-for-bug-compatability" under the old poverb that
"any sufficiently old bug becomes a feature."
 
M

Mark McIntyre

:You are still annoying with the
:non-standard quote mark.

a) There is no standard quote mark.

There's an accepted standard set. Colon isn't one of them. There may even be an
RFC on it.
b) I am not responsible for your running any particular newsreader that
does non-standard things to Usenet messages. If your reader chokes on
completely valid messages, then it is up to you to either live with it,
chuck it, fix it, or get someone to fix it for you.

Its hardly fair to people who may have no control over their newsreader (think
corporate environments. Think universities. Think...) to go around deliberately
using annoying quote styles.
to suit the straight-jacket that you have voluntarily locked yourself into.

You're assuming that people have a choice.
c) Most people do -not- use programs that automatically count '>' and
colourize.

Ya reckon? I'd be veeery interested to see how many people are using Agent,
google groups, xnews and the other readers that do precisely this.
The quoting structure I use is easier for those people to
follow.

in your opinion. Give others leave to differ.
 
C

CBFalconer

Walter said:
:You are still annoying with the
:non-standard quote mark.

a) There is no standard quote mark.

b) I am not responsible for your running any particular newsreader that
does non-standard things to Usenet messages. If your reader chokes on
completely valid messages, then it is up to you to either live with it,
chuck it, fix it, or get someone to fix it for you. Don't be going around
demanding that people change perfectly conformant RFC 1036 postings
to suit the straight-jacket that you have voluntarily locked yourself into.

c) Most people do -not- use programs that automatically count '>' and
colourize. The quoting structure I use is easier for those people to
follow. You have taken a weak convention and proclaimed it as a virtue,
and are attempting to now fossilize the broken weak convention.
You want "bug-for-bug-compatability" under the old poverb that
"any sufficiently old bug becomes a feature."

You are determined to be an ignorant and insolent boor, both with
off-topic postings and quoting habits and general trollish
behaviour. The NRC used to have better quality people. Enjoy
playing with yourself. PLONK.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top