Python: interrupt s.accept() - python

I have this code:
host, port = sys.argv[1:3]
port=int(port)
s = socket.socket()
s.bind((host,port))
s.listen(5)
while True:
conn, addr = s.accept()
threading.Thread(target=handle,args=(conn,)).start()
I need to stop my code using Ctrl-C, but Python doesn't receive Ctrl-C when it waits for new connection (s.accept()). How can I solve this problem?

In order to stop the socket connection, you can call the shutdown method like so:
s.shutdown(socket.SHUT_WR)
(This SHUT_WR stops all new writes and reads)
However, while your code is running, it is suspended while trying to make the TCP connection. In order to stop it via Ctrl-C, you'll need to run the socket on another thread, giving your main thread the ability to wake up to the interrupt and send the shutdown message.

You can use shutdown() or close() for your need
A wonderful explanation (from AIX 4.3 Communications Programming Concepts) is given below
Once a socket is no longer required, the calling program can discard the socket by applying a close subroutine to the socket descriptor. If a reliable delivery socket has data associated with it when a close takes place, the system continues to attempt data transfer. However, if the data is still undelivered, the system discards the data. Should the application program have no use for any pending data, it can use the shutdown subroutine on the socket prior to closing it.

Related

How to safely exit a socket if the python process is forcibly quit?

I'm attempting to get a simple server up and running with sockets, where it will send out the same information to any connected client. I've successfully managed to handle threads and stopping them in the case of KeyboardInterrupt, but I can't figure out how to close the socket if the script is ended early (such as the python process closed or you force run the script again).
A very basic example would be this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_process.bind(('localhost', 60000))
socket_process.listen(5)
conn, addr = socket_process.accept()
If you run that (on Windows at least), and then hit F5 to run it again, you get error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted.. It does eventually close after half a minute or something, but I'd like it to instantly close if the script that spawned it no longer exists.
Even if a timeout is set, it doesn't cause the error to go away any time sooner.
For the record, those types of exit aren't caught by atexit. I'm thinking something similar to the multiprocessing daemon option could work if it exists.

Why is adding a while loop causing unexpected behavior?

I have this client Python program, sending to a Java server program.
My client was working fine before adding the while loop. I needed to add a while loop to keep sending user input; now the text does not appear on the other end until I kill the program (the Python client), then all the text I entered in Python will appear on the other end, but only after killing the program! What causes this?
import socket
HOST = "192.168.0.76"
PORT = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
while (True):
sock.sendall(raw_input(""))
Taking a quick look at the socket docs, I noticed that there is a setsockopt() function. If you look at the docs (man setsockopt), there's a SO_SNDBUF flag, which controls the buffer size while sending. If you didn't send enough, it probably doesn't flush until there's more data.
However, there doesn't appear to be a way to flush sockets (due to TCP frame sizes), and this related answer might give you some more hints: Python Socket Flush
change the loop to:
while True:
input = raw_input("")
sock.send(input)

Better way of reading UDP data in Python

Is there a better way of listening on a port and reading in UDP data?
I do a
self.udps.bind((self.address,self.port)
ata, addr = self.udps.recvfrom(1024)
It seems to get locked in this state until it gets that data, in a bare script or in a thread.
This works well, but if you want to say get it to stop listening, it won't until it receives data and moves on to realize it needs to stop listening. I've had to send UDP data to the port each time to get it to gracefully shut down. Is there a way to get it to stop listening immediately with a specific condition?
recfrom waits until data arrives on the specified port.
If you don't want it to listen forever, set a timeout:
self.udps.bind((self.address,self.port)
self.udps.settimeout(60.0) # set 1min timeout
while some_condition:
try:
ata, addr = self.udps.recvfrom(1024)
except socket.timeout:
pass # try again while some_condition
else:
# work with the received data ...

python socket server/client protocol with unstable client connection

I have a threaded python socket server that opens a new thread for each connection.
The thread is a very simple communication based on question and answer.
Basically client sends initial data transmission, server takes it run an external app that does stuff to the transmission and returns a reply that the server will send back and the loop will begin again until client disconnects.
Now because the client will be on a mobile phone thus an unstable connection I get left with open threads no longer connected and because the loop starts with recv it is rather difficult to break on lost connectivity this way.
I was thinking on adding a send before the recv to test if connection is still alive but this might not help at all if the client disconnects after my failsafe send as the client sends a data stream every 5 seconds only.
I noticed the recv will break sometimes but not always and in those cases I am left with zombie threads using resources.
Also this could be a solid vulnerability for my system to be DOSed.
I have looked through the python manual and Googled since thursday trying to find something for this but most things I find are related to client and non blocking mode.
Can anyone point me in the right direction towards a good way on fixing this issue?
Code samples:
Listener:
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serversocket.bind(addr)
serversocket.listen(2)
logg("Binded to port: " + str(port))
# Listening Loop
while 1:
clientsocket, clientaddr = serversocket.accept()
threading.Thread(target=handler, args=(clientsocket, clientaddr,port,)).start()
# This is useless as it will never get here
serversocket.close()
Handler:
# Socket connection handler (Threaded)
def handler(clientsocket, clientaddr, port):
clientsocket.settimeout(15)
# Loop till client closes connection or connection drops
while 1:
stream = ''
while 1:
ending = stream[-6:] # get stream ending
if ending == '.$$$$.':
break
try:
data = clientsocket.recv(1)
except:
sys.exit()
if not data:
sys.exit()
# this is the usual point where thread is closed when a client closes connection normally
stream += data
# Clear the line ending
stream = base64.b64encode(stream[:-6])
# Send data to be processed
re = getreply(stream)
# Send response to client
try:
clientsocket.send(re + str('.$$$$.'))
except:
sys.exit()
As you can see there are three conditions that at least one should trigger exit if connection fails but sometimes they do not.
Sorry, but I think that threaded idea in this case is not good. As you do not need to process/do a lot of stuff in these threads (workers?) and most of the time these threads are waiting for socket (is the blocking operation, isn't it?) I would advice to read about event-driven programming. According to sockets this pattern is extremly useful, becouse you can do all stuff in one thread. You are communicate with one socket at a time, but the rest of connections are just waiting to data so there is almost no loss. When you send several bytes you just check that maybe another connection requires carrying. You can read about select
and epoll.
In python there is several libraries to play with this nicly:
libev (c library wrapper) - pyev
tornado
twisted
I used tornado in some projects and it is done this task very good. Libev is nice also, but is a c-wrapper so it is a little bit low-level (but very nice for some tasks).
So you should use socket.settimeout(float) with the clientsocket like one of the comments suggested.
The reason you don't see any difference is, when you call socket.recv(bufsize[, flags]) and the timeout runs out an socket.timeout exception is thrown and you catch that exception and exit.
try:
data = clientsocket.recv(1)
except:
sys.exit()
should be somthing like:
try:
data = clientsocket.recv(1)
except timeout:
#timeout occurred
#handle it
clientsocket.close()
sys.exit()

Zeromq with python hangs if connecting to invalid socket

If I connect to an inexistent socket with pyzmq I need to hit CTRL_C to stop the program. Could someone explay why this happens?
import zmq
INVALID_ADDR = 'ipc:///tmp/idontexist.socket'
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(INVALID_ADDR)
socket.send('hello')
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
conn = dict(poller.poll(1000))
if conn:
if conn.get(socket) == zmq.POLLIN:
print "got result: ", socket.recv(zmq.NOBLOCK)
else:
print 'got no result'
This question was also posted as a pyzmq Issue on GitHub. I will paraphrase my explanation here (I hope that is appropriate, I am fairly new to SO):
A general rule: When in doubt, hangs at the end of your zeromq program are due to LINGER.
The hang here is caused by the LINGER socket option, and happens in the context.term() method called during garbage collection at the very end of the script. The LINGER behavior is described in the zeromq docs, but to put it simply, it is a timeout (in milliseconds) to wait for any pending messages in the queue to be handled after closing the socket before dropping the messages. The default behavior is LINGER=-1, which means to wait forever.
In this case, since no peer was ever started, the 'hello' message that you tried to send is still waiting in the send queue when the socket tries to close. With LINGER=-1, ZeroMQ will wait until a peer is ready to receive that message before shutting down. If you bind a REP socket to 'ipc:///tmp/idontexist.socket' while this script is apparently hanging, the message will be delivered and the script will finish exiting cleanly.
If you do not want your script to wait (as indicated by your print statements that you have already given up on getting a reply), set LINGER to any non-negative value (e.g. socket.linger = 0), and context.term() will return after waiting the specified number of milliseconds.
I should note that the INVALID_ADDR variable name suggests an understanding that connection to an interface that does not yet have a listener is not valid - this is incorrect. zeromq allows bind/connect events to happen in any order, as illustrated by the behavior described above, of binding a REP socket to the interface while the sending script is blocking on term().
In most cases, you can bind and connect ZMQ sockets in either order, so your connect()/send() is simply waiting for the corresponding bind() at the other end, which never comes, so the program appears to hang. Check where the program is hanging by printing out some logging statements...

Categories