Я создаю сервер с использованием модулей socket
и threading
. Сервер позволяет выполнять несколько соединений. Я занимался обработкой ошибок (как показано в коде ниже). Однако есть одна ошибка, которую я не могу понять, как ее обработать.
Код (server.py):
import socket
import threading
# import pyaudio
# import json
from os import system
system('clear')
host = socket.gethostbyname(socket.gethostname())
port = 5000
buffer_size = 2048
connected_clients = {}
# Thread for listening and accepting new connections
def client_listener():
while True:
try:
# Accepts new client
connection, address = server_socket.accept()
# Creates a new thread for each connected client
handle_client_thread = threading.Thread(target=handle_client, args=(connection, address))
handle_client_thread.start()
except ConnectionAbortedError:
pass
except OSError:
pass
except KeyboardInterrupt:
pass
# Handles each connected client in a separate thread
def handle_client(client, client_address):
try:
# Receives room number
room_number = client.recv(buffer_size).decode('utf-8')
print(f'\nConnection from {client_address[0]}:{client_address[1]} ({room_number})')
# Adds new client to 'connected_clients'
connected_clients[room_number] = client
print(connected_clients)
while True:
data = client.recv(buffer_size).decode('utf-8')
# If no data is received, close the socket
if not data:
print(f'{client_address[0]}:{client_address[1]} ({room_number}) Disconnected')
connected_clients.pop(room_number)
break
# Print received data
else:
print(f'{client_address[0]} ({room_number}): {data}')
except KeyboardInterrupt:
client.close()
connected_clients.pop(room_number)
with socket.socket() as server_socket:
try:
# Prevents [Errno 48: Address already in use]
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Binds socket to host and port
server_socket.bind((host, port))
server_socket.listen()
print(f'Server hosted on {host}:{port}')
# Starts new thread for listening for new clients
client_listener_thread = threading.Thread(target=client_listener, name=client_listener)
client_listener_thread.start()
# Prevents main thread from closing
while True:
pass
except socket.error as error_message:
print(str(error_message))
except KeyboardInterrupt:
print(': Closing server...\n')
pass
Сообщение об ошибке появляется, когда я закрываю сервер с помощью прерывания клавиатуры (^ C). Когда я впервые нажимаю ^ C, сервер закрыт. Однако второй ^ C, похоже, вызывает исключение в модуле threading
.
Сообщение об ошибке:
Server hosted on 10.108.249.108:5000
^C: Closing server...
^CException ignored in: <module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1273, in _shutdown
t.join()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1032, in join
self._wait_for_tstate_lock()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
elif lock.acquire(block, timeout):
KeyboardInterrupt
Как мне поступить с обработкой этого KeyboardInterrupt без проблем, чтобы программа закрывалась без ошибок на одном ^ C? Желаемым результатом будет то, что сервер закроет соединения с каждым подключенным клиентом, закроет потоки и, наконец, завершит работу самого сервера.