无法在KeyboardInterrupt [Python]上关闭套接字

时间:2016-01-19 07:49:18

标签: python sockets

from socket import socket, AF_INET, SOCK_STREAM

sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
while True:
    try:
        connection, address = sock.accept()
        print("connected from " + address)
        received_message = sock.recv(300)
        if not received_message:
            break
        connection.sendall(b"hello")

    except KeyBoardInterrupt:
        connection.close()

所以我试图把我的头包裹在套接字周围并拥有这个非常简单的脚本 但出于某种原因,我不能用KeyboardInterrupt

杀死这个脚本

如何用KeyboardInterrupt杀死脚本,为什么我不能用KeyboardInterrupt杀死它?

7 个答案:

答案 0 :(得分:4)

  1. break退出while循环。如果没有break,循环将不会结束。
  2. 为安全起见,请检查是否设置了connection
  3. from socket import socket, AF_INET, SOCK_STREAM
    
    sock = socket(AF_INET, SOCK_STREAM)
    sock.bind(("localhost", 7777))
    sock.listen(1)
    while True:
        connection = None # <---
        try:
            connection, address = sock.accept()
            print("connected from ", address)
            received_message = connection.recv(300)
            if not received_message:
                break
            connection.sendall(b"hello")
        except KeyboardInterrupt:
            if connection:  # <---
                connection.close()
            break  # <---
    

    <强>更新

    • 有一个拼写错误:KeyBoardInterrupt应为KeyboardInterrupt
    • sock.recv应为connection.recv

答案 1 :(得分:2)

尝试向套接字添加超时,如下所示:

from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
    try:
        connection, address = sock.accept()
        print("connected from " + address)
        received_message = sock.recv(300)
        if not received_message:
            break
        connection.sendall(b"hello")
    except IOError as msg:
        print(msg)
        continue    
    except KeyboardInterrupt:
        try:
            if connection:
                connection.close()
        except: pass
        break
sock.shutdown
sock.close()

答案 2 :(得分:2)

我在Windows上遇到过这个问题。以下是我处理停止过程的方法:

    try:
        while self.running:
            try:
                c, addr = self.socket.accept()
                print("Connection accepted from " + repr(addr[1]))
                # do special stuff here...
                print("sending...")
                continue
            except (SystemExit, KeyboardInterrupt):
                print("Exiting....")
                service.stop_service()
                break
            except Exception as ex:
                print("======> Fatal Error....\n" + str(ex))
                print(traceback.format_exc())
                self.running = False
                service.stop_service()
                raise
    except (SystemExit, KeyboardInterrupt):
        print("Force Exiting....")
        service.stop_service()
        raise

def stop_service(self):
    """
    properly kills the process: https://stackoverflow.com/a/16736227/4225229
    """
    self.running = False
    socket.socket(socket.AF_INET,
                  socket.SOCK_STREAM).connect((self.hostname, self.port))
    self.socket.close()

请注意,要触发KeyboardInterrupt异常,请使用:

Ctrl + Fn + PageUp(Pause/Break)

答案 3 :(得分:1)

如果远端很少发送数据,则还应该设置连接超时。 在这种情况下,当可以检查KeyboardInterrupt时,连接将引发超时异常。

from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
try:
    connection, address = sock.accept()
    connection.settimeout(1.0)
    print("connected from " + address)
    received_message = sock.recv(300)
    if not received_message:
        break
    connection.sendall(b"hello")
except socket.timeout:
    continue
except IOError as msg:
    print(msg)
    continue
except KeyboardInterrupt:
    try:
        if connection:
            connection.close()
    except: pass
    break
sock.shutdown
sock.close()

答案 4 :(得分:1)

尝试使用timeout使程序从accept等待过程中定期“跳出”以接收KeyboardInterrupt命令。

以下是套接字服务器的示例:

import socket

host = "127.0.0.1"
port = 23333

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.bind((host,port))
sock.listen()

sock.settimeout(0.5)

print("> Listening {}:{} ...".format(host,port))

try:
    while True:
        try:
            conn, addr = sock.accept()
            data = conn.recv(1024)
            if not data:
                print("x Client disconnected!")
                break
            else:
                print("> Message from client: {}".format(data.decode()))
                msg = "> Message from server".format(data.decode()).encode()
                conn.sendall(msg)
        except socket.timeout:
            print("Timeout")
        except KeyboardInterrupt:
            pass
except KeyboardInterrupt:
    print("Server closed with KeyboardInterrupt!")

答案 5 :(得分:0)

对于Windows用户,

以上尝试捕获KeyBoard中断的解决方案似乎无效。我最终在套接字上设置了超时时间。

类似: server_socket.settimeout(10)

在闲置10秒后会引发异常(例如10秒钟没有收到任何东西)

答案 6 :(得分:0)

可以在单独的进程中捕获CTRL + C事件,然后将其发送回在主进程中运行的另一个线程以杀死套接字。以下示例已在Windows 10上使用Python 3.5.4成功测试。在周围放置一些注释和打印语句,以便您查看正在发生的情况。

from multiprocessing import Pipe, Process
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
import time

def detect_interrupt(conn):
    try:
        print("Listening for KeyboardInterrupt...")
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Detected KeyboardInterrupt!")
        print("Sending IPC...")
        conn.send(True)
        conn.close()

def listen_for_interrupt(conn, sock):
    print("Listening for IPC...")
    conn.recv()
    print("Detected IPC!")
    print("Closing sock...")
    sock.close()

if __name__ == "__main__":

    sock = socket(AF_INET, SOCK_STREAM)
    sock.bind(("localhost", 7777))
    sock.listen(1)

    # Crate a Pipe for interprocess communication
    main_conn, detect_conn = Pipe()
    # Create a thread in main process to listen on connection
    listen_for_interrupt_thread = Thread(
        target=listen_for_interrupt, args=(main_conn, sock), daemon=True)
    listen_for_interrupt_thread.start()
    # Create a separate process to detect the KeyboardInterrupt
    detect_interrupt_process = Process(
        target=detect_interrupt, args=(detect_conn,))
    detect_interrupt_process.start()

    connection = None
    try:
        while True:
            print("Running socket accept()")
            connection, address = sock.accept()
            print("connected from " + address)
            received_message = sock.recv(300)
            if not received_message:
                break
            connection.sendall(b"hello")
    except KeyboardInterrupt:
        print("Handling KeyboardInterrupt")
        sock.close()
        if connection:
            connection.close()