TCP/IP in C connection value re assigning - c

I am working on TCP/IP project (Server, and many clients). I wrote code completely in C. I have observed that whenever a new client connects to the server, function accept() returns a number for that particular connection.
newton = accept(mysocket, (struct sockaddr *)&dest, &socksize)
newcon in the above code is different for different clients. Whenever a client disconnects, the connection number which was assigned to that disconnected client is gone. That number is not going to get assigned to another client at all. if the server has many users then clients connect and disconnect lot of times. so the number go on increasing (from 0 to bigger number). How should I deal with this if the server has millions of clients connected? Is there any way that I can reuse the connection number again?

You misunderstand the return value of accept. It is not a number of connections, but a socket descriptor. (Which happens to be file descriptor, which is integer, on *nix platforms).
The same number can be returned again if one of the previously assigned sockets is closed - so, in order to maintain your scalability, make sure you close your sockets after they are no longer needed - which is a proper thing to do anyways.

Test it.
Create an array of integers, say 10000 in size. When you accept a connection, push the fd value returned into that array. Then at the end, sort the array and look for duplicates. You should see duplicates, as others have alluded to.

The server side implementation of a TCP connection is designed to support multiple concurrent connections. This behavior is achieved using the accept() system call which is invoked with the server socket as parameter. When a new connection requests arrives, the system creates a new socket to handle this new connection and this socket descriptor is returned by the accept system call. Subsequently the communication on this new connection is handled using this socket descriptor returned by accept. When the communication with client is completed, the connection is closed and this socket descriptor is returned to the system. The system can reuse the same descriptor again to handle a new client request again.
It should be noted that once the connection is closed, in certain conditions the connection moves to TIME_WAIT state and the socket is not re-used when the connection state is TIME_WAIT. The socket becomes free after the TIME_WAIT state. So this is quite possible that when one connection is assumed to be closed, it can actually be in TIME_WAIT state. This can be verified using 'netstat -anp' command.
Socket descriptors are system resources and each system has an upper limit on maximum number of open descriptors. Once that limit is reached, the system does not accept new connections. So if a client-server system has been implemented in such a way that there are not large number of concurrent TCP connections, the limit of maximum number of open descriptors is not hit and server will continue to server the clients. If the client-server system requires large number of persistent connections then definitely the limit of open descriptors can be a problem and will need to be increased.

accept returns a descriptor. You could implement a data structure, where you could store the descriptors and manipulate them. But it depends on the use case and your implementation and what you are going to do with them.

Related

one accept call for multi client requests

To begin with, I know there are ways to handle multiple client requests by forking or threading. But I cannot understand why there cannot be multiple acceptance by the server without forking or threading. accept() call can simply accept all process wish to connect to it. Why cannot the the call(accept()) go on unless a client cut its connection??
server does socket(), listen() and bind() with blocking(default) way
client does likewise by default socket() and connect()
What I think is accept's returned value will be for the recent child. But in reality it blocks until the prior client(s) cut its connection.
I wonder whether there is file-descriptor which is returned by accept() overwriting? If not, how?
There is no overwriting; accept() creates a new connected socket, and returns a new file descriptor referring to that socket - a new, distinct one each time. Of course, a server which manages all client connections without creating other threads must store all those file descriptors, e. g. in an array.

Socket programming - What's the difference between listen() and accept()?

I've been reading this tutorial to learn about socket programming. It seems that the listen() and accept() system calls both do the same thing, which is block and wait for a client to connect to the socket that was created with the socket() system call. Why do you need two separate steps for this? Why not just use one system call?
By the way, I have googled this question and found similar questions, but none of the answers were satisfactory. For example, one of them said that accept() creates the socket, which makes no sense, since I know that the socket is created by socket().
The listen() function basically sets a flag in the internal socket structure marking the socket as a passive listening socket, one that you can call accept on. It opens the bound port so the socket can then start receiving connections from clients.
The accept() function asks a listening socket to accept the next incoming connection and return a socket descriptor for that connection. So, in a sense, accept() does create a socket, just not the one you use to listen() for incoming connections on.
It is all part of the historic setup. listen prepares socket for the next accept call. Listen also allows one to setup the backlog - the number of connections which will be accepted by the system, and than put to wait until your program can really accept them. Everything which comes after the backlog is full well be rejected by the system right away. listen never blocks, while accept will block (unless the socket is in non-blocking mode) until the next connection comes along. Obviously, this does not have to be two separate functions - it is conceivable that accept() function could do everything listen does.
The above two answers clearly state the difference between accept and listen. To answer your other question - why we need two separate functions?
One use case is, for e.g. if you only want to test if a port is still available/and accessible, you can do so by just listening to the port and then closing it without accepting any connections.
For e.g. https://github.com/coolaj86/golang-test-port uses the listen call for testing a port's availability.
listen() uses a backlog parameter which specifies the maximum number of queued connections and should be at least 0. It's value increases as the server receives a lot of connection requests simultaneously.
accept() waits for incoming connections. When a client connects, it returns a new socket object representing the connection.
Another imperative thing to note is that accept() creates a new socket object which will be used to communicate with the client. It is different from the listening socket that server uses to accept new connections.
Maximum number of sockets allowed per each connection between an application and the TCP/IP sockets interface is 65535.

detecting when a client-side application shuts down the connection inorderly

I am developing a 9p server, it is pretty much like an nfs server. Subsequent mounting and unmounting causes no socket descriptor file leakage because I am able to close the socket. However, in the following scenario, the server does not do a proper clean up and close the socket. The scenario is, when the client at Machine A mount a FS from the server machine. Then for some reason, Machine A restarts or is shut down. If this happens, I am expecting the server to clean up the work and close the socket but for some reason it blocks on read(). I thought a read() should return 0 when a connection is closed but it doesnt. I assume thats because a proper tcp termination has not occured so the server is waiting for some data from the client. Here is a pseudo code of my server
while(1){
n = read(sockfd, buffer, 4); //4 is protocol header that specifies the size
if ( n == 0 ) break;
/* iteratively read the rest of bytes until the incoming message ends */
}
cleanup(); // close socket and some other tasks
However, when the client restarts while the server is blocking on read, nothing happens. What is the best way and easiest to solve this? Some people suggest running a separate thread that checks connections but this is too involved. I am sure there must be a faster way
When the client does a shutdown then the OS on client terminates all TCP connection. But when the client crashes or it is switched off or when an network problem occurs somewhere at path between the client and the server then there is no way to deliver an information to server and the server may be blocked in the read() call forever.
There are two possible solutions. Either you can use standard TCP keep alive probes or you can implement an application level health-check.
TCP keep alive
TCP keep-alive is well described for example at http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html :
In order to understand what TCP keepalive (which we will just call keepalive) does, you need do nothing more than read the name: keep TCP alive. This means that you will be able to check your connected socket (also known as TCP sockets), and determine whether the connection is still up and running or if it has broken...
When you want you application use TCP keep alive the just set the socket option (error checking is missing):
int optval = 1;
socklen_t optlen = sizeof(optval);
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
The TCP keep alive is easy to use but it depends on the OS configuration and application cannot set own timeouts because they are configurable system wide.
Application level health check
Use an application level mechanism when you need application specific timeouts for disconnection detection. There are plenty of ways how to implement it. The idea is to send periodically a piece of useless data and assume connection is destroyed when it is not received.
I want to amend Zaboj Campula's good answer with the most important way to deal with this: Timeouts. Normally, you would assign a timeout to any socket operation. A typical value is 30 seconds. That way there is no need for keep alives most of the time. Connection failure will be detected within 30 seconds.
Some people suggest running a separate thread that checks connections but this is too involved.
That does not work because your machine does not know that the connection is gone. There is nothing to check.

C/Linux TCP Socket Server

I'm implementing a TCP socket server in C and Linux. It will be a chat server handling many requests simultaneously. Here is the pseudo code for how it is setup
create a socket
bind to a well-known port
use listen to place in passive mode
while (1)
{
accept a client connection
fork
if (child)
{
communicate with new socket
close new socket
exit
}
else
{close new socket}
}
From what I've seen, the "communicate with new socket" part consists of reading the buffer and then possibly writing to the buffer, then the socket closes. I thought sockets were suppose to be a persistent connection? If the client has to reconnect every time it wants to send more data to the server, isn't this inefficient and defeating the purpose of sockets?
If the client has to reconnect every time it wants to send more data to the server, isn't this inefficient and defeating the purpose of sockets?
It's impossible to say without knowing more about the nature of your application:
In some cases, it makes sense to maintain a persistent connection for the duration of the client's lifetime.
In other cases, connecting on every message would also work well.
You are quite right on the efficiency front: there is quite a lot of overhead involved in establishing a TCP connection. Therefore, if the messages are frequent it may turn out to be very costly to set up a new connection for each message.
Don't close the socket. Put the code which receives and responds to the messages in a loop and using blocking I/O ( the default ) to block on reading the socket until a request arrives. This way you'll have a forked process dealing with each client and using minimal resources. You only close the socket and exit the child process when the client explicitly closes the connection because it's done.
Use UDP instead of TCP. This way there is no "connection" between the server and the client. You multiplex multiple clients to a single socket without forking. If you care about reliability you'd need to add a sequence number to each message to keep them straight and allow retransmission on failures.
Keep a single process using TCP, but store a socket descriptor set and use select to check for readable sockets. You can then retransmit that data on each or some of the other client sockets.
I'd point out that forking a child for each client in a chat server seems like a poor implementation. How do two people who want to chat communicate? Each one will be served by a separate process - how do the processes communicate with each other so that chat data can pass between clients?

Is it possible for me to accept a connection and have it die withouit my knowing, then accept antoher connection on the same socket number?

Is it possible for me to accept a connection and have it die withouit my knowing, then accept another connection on the same socket number?
I've got a thread to do protocol parsing and response creation. I've got another thread to handle all my network IO and one more thread to handle new incomcing connection requests. That makes three threads total. Using select in the IO thread, I get a failure and have to search for the dead socket. I am afraid there is the case that accept might want to accept a new connection on a socket number that was previous dead.
I'd assume this can't happen until I "shutdown() || close();" the socket that may be dead on the server side. If it could happen, is the only solution to setup mutexes to halt everything while I sort out what sockets have gone bonkers?
Thanks,
Chenz
A socket descriptor wont get reused until you close it.
Assuming we're talking TCP, then if the remote side closes its send side of the connection then you'll get a recv() returning 0 bytes to tell you of this. Since TCP support half closed connections you could still be able to send data to the remote side of the connection (if your application level protocol is made that way) or you might take the fact that the remote side has closed its send side as an indication that you should do the same.
You use shutdown() to close either your send side or your recv side or both sides of the connection. You use close() to close the socket and release the handle/descriptor for reuse.
So, in answer to your question. No, you wont be able to accept another connection with the same socket descriptor until you call close() on the descriptor that you already have.
You MAY accept a connection on a new socket descriptor; but that's probably not a problem for you.

Resources