why netty can not make a distinction between socket close and socket half close - nio

i got an interest problem, when i close (OIO) socket outputstream with half close manner, Netty server detect the event and trigger the ChannelClose method in handler, but in client side, the socket is open and connected, then i complete close socket in client, but this time, Netty server get no reflect.
doesn't it very strange?

Nobody can tell the difference. Shutdown for output sends a FIN. Close sends a FIN, unless it has already been sent, i.e. by a shutdown. FIN appears at the receiver as the EOS (EOF) condition. The server got the FIN from the shutdown, saw that as EOS, closed the socket, your client got the FIN, saw that as EOS, closed the socket, and sent ... nothing to the server, because the FIN had already been sent.

Related

Does a recv() already waiting for data detect shut down of the socket from the other end?

I am transferring the contents of a file to a client and on completion of the transfer I shut down the TX socket (shutdown(hdl, SHUT_WR)). The client side depends on the detection of orderly shut down of the socket to exit the loop for receiving data.
I notice that the detection happens (recv() returns 0) only sometimes while other times it just blocks. I suspect a race condition between the shutdown() and the final recv() i.e. when the socket is closed before the recv() call is made I can detect the orderly shut down, however if the recv() is already blocking for data and the socket is shutdown() at this point then the client is unable to detect it.
Is my diagnosis right?
Irrespective of the answer to the above question - how do I better handle detection of end of transmission without resorting to OOB means?
P.S. : If it matters - I am using CYGWIN on a Windows 8.1 machine.

when the server's child close socket

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

How to handle socket read in C when the remote server closes socket possibly before read is finished?

Client blocks on the read call waiting to read n bytes.
Server writes n bytes and closes the connection immediately.
Can read call return negative or zero in this case if the socket gets closed before read is finished or due to some other issue? (client/server running on same linux box in this case)
I am facing such a scenario but not sure how this works in TCP/IP subsystem and how to resolve it.
Sever:
write
close
Client:
read
close
The safe way to close a socket connection is first calling shutdown to signal that you won't be writing, keep reading the data that the remote side sends, and then shutdown the reading side and close the socket. If you close the socket before reading data sent to you the OS resets the connection (sends a packet with the RST flag set) and the remote side interprets this as an error.
TCP treats the connection serially, and the reader processes everything in the order that the sender transmitted. When the sender closes the connection, the reader will get an EOF after it has read all the data that was sent, not before.

Graceful Shutdown Server Socket in Linux

I want to be able to stop listening on a server socket in linux and ensure that all connections that are open from a client's point of view are correctly handled and not abruptly closed (ie: receive ECONNRESET).
ie:
sock = create_socket();
listen(sock, non_zero_backlog);
graceful_close(sock);
if thought calling close() and handling already accept'd sockets would be enough but there can be connections that are open in the kernel backlog which will be abruptly closed if you call close() on the server socket.
The only working way to do that (that I have found) is to:
prevent accept() from adding more clients
have a list of the open sockets somewhere and to wait until they are all properly closed which means:
using shutdown() to tell the client that you will no longer work on that socket
call read() for a while to make sure that all the client has sent in
the meantime has been pulled
then using close() to free each client socket.
THEN, you can safely close() the listening socket.
You can (and should) use a timeout to make sure that idle connections will not last forever.
You are looking at a limitation of the TCP socket API. You can look at ECONNRESET as the socket version of EOF or, you can implement a higher level protocol over TCP which informs the client of an impending disconnection.
However, if you attempt the latter alternative, be aware of the intractable Two Armies Problem which makes graceful shutdown impossible in the general case; this is part of the motivation for the TCP connection reset mechanism as it stands. Even if you could write graceful_close() in a way that worked most of the time, you'd probably still have to deal with ECONNRESET unless the server process can wait forever to receive a graceful_close_ack from the client.

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