I have a classic TCP server that accepts connections with system call accept().
In a specific situation I have n connections accepted and so n childs created.
I need to stop connection when generic event A occurs on the server. What is the best way to close socket in server and in client?
Now I do it such way: when event A occurs, server sends a specific message to client and then it executes close(). Client reads socket and if the message is the special message it closes.
But if I need to do something else in the client this way is very bad. What can I do?
By 'n childs created' I assume you mean n child processes, with each child process handling the TCP connection to one client program?
If so, one way to handle it would be to have your server's parent-process keep track of the process IDs (as returned by fork()) of the child processes it has spawned (via a list or lookup-table or similar). Then when you need a particular connection to go away, your server's parent-process can call kill(the_child_process_id, SIGTERM) or similar to get the child-process to go away ASAP. (SIGTERM asks nicely; if you want to go full-nuclear you could specify SIGKILL instead).
In any case, once the child-process on the server has received the signal and exited, the OS will make sure that the server's side of the TCP connection is closed, and the client's OS will then be notified that the TCP connection is closed, and based on that, the client (if it is coded correctly to handle remote-closed connections, i.e. to react to recv() returning 0 by closing its own TCP socket) will then do the right thing as well.
Related
I'm making a concurrent server/client program in C using threads. Whenever a client connects, I create a new thread to handle it.
My problem is: I want to be able to close the server, from the client. With the command '..' for example. When I type '..' in the client, I want the server to close immediately.
I thought about having a global variable, that indicates wether the server should close or not. The problem is: When the thread is created to handle the client, the main thread goes back to accept(), and it cannot check that variable. So, it will only close when a new client connects.
Any ideas on how to solve this?
Thanks!
Use select() or (e)poll() or equivalent to wait for a client to connect BEFORE you then call accept() to accept the connection. Those kind of functions allow you to specify a timeout, that will allow you to stop waiting periodically to check for other conditions, like a shutdown request. On some platforms, you can even have these functions wait on not only the listening socket but also a separate pipe that you create privately for yourself, and when you want to "wake up" your waiting loop to do something, simply write a byte into that pipe, and when the loop detects that byte arriving then it can act accordingly.
I'm testing some code in C and I've found strange behaviour with TCP socket calls.
I've defined one listening thread which accepts clients synchronously and after accepting the client it process it in a for loop until it disconnects. Thus only one client at a time is handled. So I call accept in a loop and then recv in an inner loop until received an empty buffer.
I fire 5 threads with clients, I call connect, send and finally close
I get no error in any call. Everything seems to be fine.
However when I print received message on the server side it turns out that only the first client got through to the server, i.e. accept never fires on other clients.
So my questions are:
Shouldn't connect wait until server calls accept? Or is the kernel layer taking care of buffering under the hood?
If it's not the case then shouldn't the server be able to accept the socket anyway, even if it is in a disconnected state? I mean is it expected to lose all the incoming data?
Or should I assume that there's a bug in my code?
The TCP state-machine performss a synchronized dance with the client's state machine. All of this is performed at OS-level (The TCP/IP stack); the userspace process only can do some systemcalls to influence this machinery now and then. Once the client calls listen() this machinery is started; and new connections will be establisched.
Remember the second argument for listen(int fd, int backlog) ? The whole 3way handshake is completed (by the TCP stack) before accept() delivers the fd to the server in userland. So: the sockets are in connected state, but the user process hasn't picked them up yet (by calling accept() )
Not calling accept() will cause the new connections to be queued up by the kernel. These connections are fully functional, but obviously the data buffers could fill up and the connection would get throttled.
Suggested reading: Comer& Stevens: Internetworking with TCP/IP 10.6-10.7 (containing the TCP state diagram)
On the concurrent server, server spawns many children(assume that I am using multiple process when clients connet). So, if client close sockets(close() function), it sends FIN to server and receive ACK from the server.
Finally, server's read() function returns 0 and exit() function is called. It causes server child to terminate and close socket, and send FIN to its client.
In this situation, how can server receive ACK even though server's child socket is closed? and how can server re-send FIN when client doesn't receive the FIN even though there is no connected socket because of child which is terminated?
Does kernel keep that terminated process's socket until finishing final four-handshaking although it is closed?
Yes it does. close() is normally asynchronous.
Yes, close() on sockets is normally asynchronous, and sockets can linger after application is terminated. You can easily see them in netstat output in their approriate state (for example, TIME_WAIT or FIN_WAIT2).
Okay I'm brand new to socket programming and my program is not behaving like I'd expect it to. In all the examples that I see of socket programming they use accept() and all the code after assumes that a connection has been made.
But my accept() is called as soon as I start the server. Is this supposed to happen? Or is the server supposed to wait for a connection before executing the rest of the program?
EDIT: Oops I forgot to mention it is a TCP connection.
I think this is what you're after.
http://www.sockets.com/winsock.htm#Accept
The main concept within winsocket programming is you're working with either blocking or non blocking sockets. Most of the time if you're using blocking sockets you can query the sockets recieve set to see if any call would result in your call to the routine being blocked..
For starting off with this UDP is easier considering its a datagram protocol. TCP on the other hand is a streaming protocol. So it's easier to think in regards to blocks of data that is sent and received.
For a server, you:
Create the socket - socket().
Bind it to an address.
You enter a loop in which you:
Listen for connection attempts
Accept and process them
It is not clear from your description whether you are doing all those steps.
There are multiple options for the 'process them' phase, depending on whether you plan to have a single-threaded single process handle one request before processing the next, or whether you plan to have a multi-threaded single process, with one thread accepting requests and creating other threads to do the processing (while the one thread waits for the next incoming connection), or whether you plan to have the process fork with the child processing the new request while the parent goes back to listening for the next request.
You are supposed to enter your acceptance loop after you have started listening for connections. Use select() to detect when a pending client connection is ready to be accepted, then call accept() to accept it.
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.