user713867
user713867

Reputation:

Working for accept() system call

I have to write a program which will check how many clients can connect to a single server(socket) in C.

I used Beej's guide to programming as a reference, and have realized that after a single client connects to the server, more clients cannot simultaneously send messages to the same server. Only after the first connection is closed will the backlogged message from the second client be delivered.

Since my newness to socket programming, I'm not sure if "accept" is the correct system call to be used. Also, what should the value of BACKLOG be in listen to make to see the stress the server can handle.

Any help?

Upvotes: 2

Views: 2648

Answers (2)

David Schwartz
David Schwartz

Reputation: 182763

Section 7.2 of Beej's guide covers the way to do this that most C programmers learn first. The example at the end of section 7.2 should be exactly what you want.

Basically, you use select to let your program wait for either data to be received on one of the connections you have already accepted or for a new client to be trying to connect. Then you check to see what happened and handle it. (Unfortunately, the example does teach one bad habit -- it forgets to set the sockets to non-blocking mode, so it can deadlock in accept if the connection is no longer pending.)

The basic idea is this:

1) Set up basic structures to keep track of clients, initialize them to reflect the fact that you have no clients.

2) Set up a listening socket for new connections.

3) Wait for something to happen using select. You can wait for a new client to connect, data to be received from an existing client, data to be able to be sent to an existing client, an error to occur on an existing connection, or a certain amount of time to pass. Use the structures that track your clients to make sure you wait for data to be received from all your existing clients.

4) Handle whatever happened. If a new client tries to connect, accept the connection and update your tracking structures. If data was received from a client, see if it completes a command and, if so, process it. If one of your clients closed the connection or there was an error on that connection, clean up by closing your socket and updating the tracking.

5) Go back to step 3.

This is called 'I/O multiplexing'. There are other ways to do it, but this is the way most C programmers learn first.

Upvotes: 2

Alnitak
Alnitak

Reputation: 339796

accept() is the right system call. It returns a new file descriptor associated with the new incoming connection, whilst leaving the original socket prepared to receive more connections.

However once you've accepted that incoming connection, it's usual to have the main process either:

  1. create a thread to handle that socket
  2. fork a new process which inherits the new file descriptor.
  3. use select(), epoll(), etc to poll for reads on that socket

If you don't do that, any subsequent read() on the accepted connection will block, meaning that you can't call accept() again.

The backlog parameter to listen() only serves to tell the kernel how many sockets may be allowed to remain in their initial "connecting" state prior - it's not normally necesssary to tune it very much.

Upvotes: 2

Related Questions