Frage

I'm playing around with sockets in python, just for the purpose of learning about them. However I am really annoyed with the following problem:

import socket
soc = socket.socket(socket.AF_INET)
soc.bind(('localhost',8000))
soc.listen(0)
client = soc.accept()

While the socket is waiting for a connection, pressing ctrl-c does not quit the application.

How can I quit the application?

A similar issue was addressed in these two questions, but there the accept method was called from a separate thread and the problem was how to make ctrl-c kill that thread. Here the accept method is called from the main thread.

Edit: I am running python 3.3.0 on Win7 64 bit.

War es hilfreich?

Lösung 2

I couldn't find a way to kill the application using ctrl-c or any other way except for killing it through the task manager, so I wrote a workaround:

import socket,os
from threading import Thread

class socketListener(Thread):
    def run(self):
        soc = socket.socket(socket.AF_INET)
        soc.bind(('localhost',8000))
        soc.listen(0)
        client = soc.accept()

pid = os.getpid()
sl = socketListener()
sl.start()
input('Socket is listening, press any key to abort...')
os.kill(pid,9)

This runs the script in a separate thread, while waiting for a keystroke in the main thread. Once the user presses a key, the entire application is killed.

Andere Tipps

You should use CTRL + Break. That should kill it.

"serversocket" module provides the standard solution. I tested Control-C on Windows, it worked.

This is the link, serversocket example

The Control-C handling is even mentioned in the comment of the code

# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C

Here is the complete code from the above link:

import socketserver   
class MyTCPHandler(socketserver.BaseRequestHandler):   
    def handle(self):
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        # just send back the same data, but upper-cased
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
        # Activate the server; this will keep running until you
        # interrupt the program with Ctrl-C
        server.serve_forever()

If we wanted to re-invent the wheel, we would do a select() or poll() on the listener socket, with a timeout 0.5 seconds.

To save time of the other people searching for this topic, if you laptop keyboard does not have a break button, please try

Ctrl + Fn + F6

or

Ctrl + F6

After being myself confronted to the same problem I found a little workaround, it might not be the cleanest way but at least it works for me :

import socket
from select import select

#create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#bind the socket to localhost
serversocket.bind(('localhost', 8000))
While 1:
    serversocket.listen(5)
    ready, _, _ = select([serversocket], [], [], 1) #Timeout set to 1 seconds
    if ready:
        (clientsocket, address) = serversocket.accept()
        #Do something with client
    else:
        #Do nothing, just loop again

By using select you will wait a change on the socket fd until the end of the timeout. As I said this might not be the cleanest way but Ctrl-c will be catch at the end of the timeout.

Portability alert: On Unix, select works both with the sockets and files. On Windows, select works with sockets only.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top