键盘中断不能完全退出

时间:2018-01-05 08:06:07

标签: python multithreading

我正在使用套接字代码,我通过线程处理客户端。用例是这样的, 1.服务器运行并且客户端开始连接它。 2.交互后客户端发出退出消息,服务器关闭客户端连接。 3.但是我想要的是万一在服务器上发生了什么事情,如果我手动命中服务器上的ctrl-c,它应该退出所有线程和主程序。

以下是我的尝试,但遗憾的是并非一切都得到了清理,我必须两次点击ctrl-c。

import socket
import sys
from threading import Thread

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

    # This is to prevent the socket going into TIME_WAIT status and OSError
    # "Address already in use"
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error as e:
    print('Error occured while creating the socket {}'.format(e))

server_address = ('localhost', 50000)
sock.bind(server_address)

print('**** Server started on {}:{} ****'.format(*server_address))

sock.listen(5)


def client_thread(conn_sock, client_add):
    while True:
        client_msg = conn_sock.recv(1024).decode()
        if client_msg.lower() != 'exit':
            print('[{0}:{1}] {2}'.format(*client_add, client_msg))
            serv_reply = 'Okay ' + client_msg.upper()
            conn_sock.send(bytes(serv_reply, 'utf-8'))
        else:
            conn_sock.close()
            print('{} exitted !!'.format(client_add[0]))
            sys.exit()


try:
    # Keep the server until there are incominmg connections
    while True:
        # Wait for the connctions to accept
        conn_sock, client_add = sock.accept()
        print('Recieved connection from {}:{}'.format(*client_add))
        conn_sock.send(
            bytes('***** Welcome to {} *****'.format(server_address[0]), 'utf-8'))
        Thread(target=client_thread, args=(conn_sock, client_add)).start()

except Exception as e:
    print('Some error occured \n {}'.format(e))
except KeyboardInterrupt as e:
    print('Program execution cancelled by user')
    sys.exit(0)

finally:
    sock.close()

以下是我的代码的执行跟踪

**** Server started on localhost:50000 ****
Recieved connection from 127.0.0.1:35910
[127.0.0.1:35910] ,msdasda
^CProgram execution cancelled by user
^CException ignored in: <module 'threading' from '/apps/nttech/rbhanot/anaconda3/lib/python3.6/threading.py'>
Traceback (most recent call last):
  File "/apps/nttech/rbhanot/anaconda3/lib/python3.6/threading.py", line 1294, in _shutdown
    t.join()
  File "/apps/nttech/rbhanot/anaconda3/lib/python3.6/threading.py", line 1056, in join
    self._wait_for_tstate_lock()
  File "/apps/nttech/rbhanot/anaconda3/lib/python3.6/threading.py", line 1072, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

所以有人可以建议我如何在发生keyboardInterrupt时关闭所有内容。

1 个答案:

答案 0 :(得分:0)

我通过将线程作为守护进程来实现它,因此主程序将在接收到KeyboardInterrupt时退出,并且线程将继续在后台运行。