Python - closing a server socket while it's waiting for accept() - sockets

I've been scouring for an hour to find an answer on this one -- got close, but not quite there.
The issue is that I'm using this basic approach to implement a socket server, but (of course) it hits the line with the accept() and freezes there. What I want is to be able to have the user click a checkbox control in a Tkinter GUI and have the socket be listening, or closed, on demand. A flag/semaphore to control the while loop doesn't help by itself; in concert with that, I also have to send a 'dummy' connection to get the server to iterate through the loop instead of just sitting at the accept() forever. Which would work of course, but it just feels klunky.
After much effort I found this article but the solution -- while it's a nice one -- still seems to still depend on the connection handler to raise the event that triggers the exit. Which in turn means that I'd still need some kind of dummy connection to make it happen, instead of being able to interrupt/destroy/whatever the server socket while it's stopped at the accept().
So is there any way to get around needing a connection before you can get the server socket closed?

Related

Difference between closing a socket and closing a network stream (System.Net.Sockets)

I have a proxy server implemented, after sending the final response to client if I directly close the socket (System.Net.Sockets TCPClient.Client.Close()) then client end receives connection aborted error but instead if I use System.Net.Sockets TCPClient.getStream().Close(), it works successfully.I want to understand what's the difference and why is client side receiving an error in the first scenario?
I would say, that Close of sockets is not trivial operation as most people think :)
First of all, you should understand the how the close should be done correctly. Basically, you have to consider that close is a kind of message like any other message sent out your socket. Or other words close() is an information on the other side of communication that the peer finished some kind of work.
Now the important thing to understand that having a TCP socket you can inform the peer that you finished sending or finished listening.
On this page, you can check out how it works in the background (note that ACK and FIN are IP layer messages so even using plain sockets implementation you will never see them): http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
So now the more practical step. Please consider that you have a client and server. The server needs to receive a message and close the connection. Please consider that client is just going to send a message and then closes the connection. If you will also consider that networks need some time to process your communication, you will realize that if you do it quickly, client will close the connection before server received your message. If you can the TCPClient.Client.Close() client will stop listening for anything (that means also for information about that the server closed the connection). So here comes the TCP stack to play (windows does it for you) - in case you will close this way the socket, TCP stack, needs to inform the server site that whatever server has sent goes to dump. So that's why you have an exception.
So the correct way is to:
inform the server that client finished sending any data (FIN)
wait until server confirms that he knows that client will not send any data (ACK)
now server should inform client that will stop sending data (FIN)
now the client can say - "ok I got it, I will not listen anymore" (ACK)
Anyway, the C# TCPClient seems to hide the logic of the background socket closing routine, but if you will not call the close sequence correct way, you'll end up with errors.
I hope that this little bit long explanation will help you understand how it works in the background and finally let you understand why.
It's also a good way to read more about TCP protocol details if you wish to learn more: http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm
I suppose that in order to close connection, you need to send some special bytes sequence. And looks like it is implemented only by tcpclient library , and not implemented by socket library. Probably something like Eof should be sent.
You may check it by some net traffic utilities like tcpdump.
Good luck!

Proper way to close a socket to avoid "connection reset by peer"

I have a client/server app that maintains a socket continuously. When the client signs off, it sends a 'signing off' message to the server and then closes the socket and cleans up. The server cleans up and closes the socket when it receives this message - and does not reply to the message.
On a fairly regular basis, I see "connection reset by peer" errors getting logged by the server without any complaints from end users, and I figure this must be an occasional timing issue in my sign-off sequence. I do see the same errors when end users complain about their connections actually being dropped, so I'm wondering how to tell the difference between those scenarios - or even better, how to prevent the bogus 'connection reset' scenario in the normal case.
I'm guessing that in some cases the server's getting hit by the closed socket before (or during) receipt of the "signing off" message. Is this possible? Is there a proper sequence you're supposed to follow for letting a server know that the client is about to terminate before actually closing the socket? Some way to check that the last message was delivered prior to closing?
Thanks,
Rob
The shutdown(s, SHUT_RDWR) function should solve your problem. There's a more complete explanation in this document.
This usually means that you have either written to a connection that had already been closed by the peer, or closed a connection without reading all the pending incoming data. In other words, an application protocol error.

How to detect when socket connection is lost?

I have a script (I don't have the code example here at the moment but I used IO::Async) which connects to socket on a remote server and listens. Client usually just listens for new data.
Problem is that the client is not able to detect if network problems occur and the socket connection is gone.
I used IO::Async and I also tried it with IO::Socket. Handle is always "connected" after the initial connection is established.
If the network connection is established again the socket connection is naturally still lost because the script has no idea that it should reconnect.
I was thinking to create some kind of "keepAlive" which "pings" (syswrite) the socket every X seconds (if nothing new came through socket) to check whether the connection is still there.
Is this the correct way to do it or is there maybe an another more creative or cleaner solution?
You can set the SO_KEEPALIVE socket option which, for TCP, sends periodic keepalive messages, and may help detect this condition. If this is detected, you will be delivered an EOF condition (most likely causing the containing IO::Async::Stream to fire on_read_eof).
For a better solution you might consider some sort of application-level keepalive message, such as IRC's PING command.
The short answer is there is no default way to automatically detect a dropped socket in perl.
Your approach of pinging would probably work pretty well; you could run a continuous thread in the background that sends ping requests and if it doesn't receive a response the main thread can be notified and a reconnect should be issued.
If you want to get messy you can work with select() to detect keep alive messages; however this may require some OS configuration depending upon your platform.
See this thread for more details: http://www.perlmonks.org/?node_id=566568

TCP recover connection after hardware disconnect

I've got a program that continuously writes to a TCP socket. I want to make sure that if the connection between the client and server is disconnected for any amount of time, the connection can be restablished.
Right now, I can disconnect the wire, and while the write() function loops, it returns one "connection reset by peer" error, and then the value of ULLONG_MAX. Then, once I replug the wire, write() continuously returns "broken pipe" errors. I've tried to close and reopen the connection but I continue to get the "connection reset by peer" error.
Does anyone know how I could either restablish the connection or keep it alive for a certain amount of time (or indefinitely) in the first place?
You cannot re-use file descriptor here, you have to start from scratch again - create new socket(2) and call connect(2) on it.
I'm afraid you have to establish a new connection, and that can only initiated by the client program. You might need some way to ensure it's the same client reconnecting maybe check the IP or exchange a token on first connection, so you can do some different kind of initiation on your connection for first connection and recovery. That solution needs some programming on your account, though..
If TCP is not for some reason the only choice, you might want to think about UDP communication, since there the part that decideds when a connection is lost is left to you. But you'll need to take care of a lot of other thinks (but since you are aiming for a lost and recover communication, that might be more to your needs).

How to hand-over a TCP listening socket with minimal downtime?

While this question is tagged EventMachine, generic BSD-socket solutions in any language are much appreciated too.
Some background:
I have an application listening on a TCP socket. It is started and shut down with a regular System V style init script.
My problem is that it needs some time to start up before it is ready to service the TCP socket. It's not too long, perhaps only 5 seconds, but that's 5 seconds too long when a restart needs to be performed during a workday. It's also crucial that existing connections remain open and are finished normally.
Reasons for a restart of the application are patches, upgrades, and the like. I unfortunately find myself in the position that, every once in a while, I need to do this kind of thing in production.
The question:
I'm looking for a way to do a neat hand-over of the TCP listening socket, from one process to another, and as a result get only a split second of downtime. I'd like existing connections / sockets to remain open and finish processing in the old process, while the new process starts servicing new connectinos.
Is there some proven method of doing this using BSD-sockets? (Bonus points for an EventMachine solution.)
Are there perhaps open-source libraries out there implementing this, that I can use as is, or use as a reference? (Again, non-Ruby and non-EventMachine solutions are appreciated too!)
There are a couple of ways to do this with no downtime, with appropriate modifications to the server program.
One is to implement a restart capability in the server itself, for example upon receipt of a certain signal or other message. The program would then exec its new version, passing it the file descriptor number of the listening socket e.g. as an argument. This socket would have the FD_CLOEXEC flag clear (the default) so that it would be inherited. Since the other sockets will continue to be serviced by the original process and should not be passed on to the new process, the flag should be set on those e.g. using fcntl(). After forking and execing the new process, the original process can go ahead and close the listening socket without any interruption to the service, since the new process is now listening on that socket.
An alternative method, if you do not want the old server to have to fork and exec the new server itself, would be to use a Unix-domain socket to communicate between the old and new server process. A new server process could check for such a socket in a well-known location in the file system when it is starting. If present, the new server would connect to this socket and request that the old server transfer its listening socket as ancillary data using SCM_RIGHTS. An example of this is given at the end of cmsg(3).
Jean-Paul Calderone wrote a detailed presentation in 2004 on a holistic solution to your problem using Twisted, including socket migration and other issues.