Shutdown python socket server by pressing CTRL+C

Asked

Viewed 30 times

0

I have a server program using a python socket that has two threads: the Accept thread, responsible for accepting new connections from clients, and the clientThread thread, responsible for handling connections and receiving messages. The clientThread thread is created by the Accept thread - I don’t know if this is a good way to do it.

I am running this application on the console and what I want to do is close the program by pressing CTRL + C. I am using signal.signal to capture when the user presses CTRL+C and manipulates a variable that indicates that the key combination has been pressed. Also, I’m using the sys.exit() to terminate the program. However, by pressing CTRL+C, the code interprets that this combination has been pressed, but is not terminated. I have read some similar topics and all indicate the sys.exit() to end the program, but, it doesn’t work with me. Any idea what I’m doing wrong?

Here is my code:

import socket
import select
import sys
import _thread
import json
import threading
import signal
import time
import os
from datetime import datetime

fechada = False
clienteThread = []

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

if len(sys.argv) != 2:
    print ("numero da porta?")
    exit()

header = 10
listaComandos = ['SEND','SENDTO','WHO','HELP']
aux_ListaSockets = []

# endereco localhost 
enderecoIP = "127.0.0.1"

#numero da porta
port = int(sys.argv[1])

#liga o servidor no localhost e na porta especificada
server.bind((enderecoIP, port))

#no maximo 20 conexoes ativas
server.listen(20)

listaDeSockets = [server]

# fim da configuracao do servidor
listaDeClientes = []

# Função para o tratamento das mensagens
def _message(client_socket):
    try:
        message_header = client_socket.recv(header)
        if not len(message_header):
            return False
        message_length = int(message_header.decode('utf-8').strip())
        return {'header': message_header, 'data': client_socket.recv(message_length)}

    except:
        return False


def clientThread(sockCliente, endereco):

    data_atual = datetime.now()
    data_hora = data_atual.strftime('%H:%M')
    usuario = _message(sockCliente)

    #Checando se o usuário já existe
    usuario_decode = usuario['data'].decode('utf-8')
    if usuario_decode in listaDeClientes:
        str_fechamento = "recusada".encode('utf-8')
        sockCliente.send(str_fechamento)
        sockCliente.close()
    else:
        str_fechamento = "aceita".encode('utf-8')
        sockCliente.send(str_fechamento)
        print(data_hora + '\t'+ usuario['data'].decode('utf-8') + '\t' +'Conectado')
        listaDeClientes.append(usuario_decode)
        aux_ListaSockets.append(sockCliente)

    while True:     

        try:
            if fechada:
                sys.exit(0)
                break
            message = sockCliente.recv(2048)
            #print(message.decode('UTF-8'))
            if message:

                if 'SEND' in message.decode("UTF-8") and ('SENDTO' not in message.decode("UTF-8")):
                    msg = message.decode("UTF-8")

                    if " " in msg:
                        msg = msg.replace("SEND","")

                    if not msg or ('SEND' in msg):
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'SEND\t' + 'Executado: Não')
                        sockCliente.send("nao_executada".encode('utf-8'))
                    else: 
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'SEND\t' + 'Executado: Sim')
                        print(usuario_decode + ' diz: ' + msg)
                        sockCliente.send("executada".encode('utf-8'))

                elif 'SENDTO' in message.decode("UTF-8"):
                    msg = message.decode("UTF-8")

                    if " " in msg:
                        msg = msg.replace("SENDTO","")

                    if not msg or ('SENDTO' in msg):
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'SENDTO\t' + 'Executado: Não')
                        sockCliente.send("nao_executada".encode('utf-8'))
                    else: 
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'SENDTO\t' + 'Executado: Sim')
                        destino = msg.split()[0]

                        if destino in listaDeClientes:
                            indexDestino = listaDeClientes.index(destino)
                            socketDestino = aux_ListaSockets[indexDestino]
                            message_sendto = 'mensagem->' + usuario_decode + ' diz: ' + msg.split()[1]
                            socketDestino.send(message_sendto.encode('utf-8'))
                            sockCliente.send("cliente existe".encode('utf-8'))

                        else:
                            sockCliente.send("cliente não existe".encode('utf-8'))

                elif 'WHO' == message.decode("UTF-8"):
                    msg = message.decode("UTF-8")
                    if not msg:
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'WHO\t' + 'Executado: Não')
                        sockCliente.send("nao_executada".encode('utf-8'))
                    else:
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'WHO\t' + 'Executado: Sim')
                        msg = json.dumps(listaDeClientes).encode()
                        sockCliente.send(msg)

                elif 'HELP' == message.decode("UTF-8"):
                    msg = message.decode("UTF-8")
                    if not msg:
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'HELP\t' + 'Executado: Não')
                        sockCliente.send("nao_executada".encode('utf-8'))
                    else:
                        data_atual = datetime.now()
                        data_hora = data_atual.strftime('%H:%M')
                        print(data_hora + '\t' + usuario_decode + '\t' + 'HELP\t' + 'Executado: Sim')
                        msg = json.dumps(listaComandos).encode()
                        sockCliente.send(msg)

                elif message:
                    sockCliente.send("comando não existe".encode('utf-8'))

            else: 
                remove(sockCliente)
        except: 
            break
        
def signal_handler(arg1, arg2):
    global fechada
    fechada = True

def acceptConnection():
    while True:
        if fechada:
            for cliente in clienteThread:
                cliente.join()
            sys.exit(0)
            break
        else:
            cliente_socket, enderecoIpDoCliente = server.accept()
            listaDeSockets.append(cliente_socket)
            cliente = threading.Thread(target=clientThread, args=(cliente_socket, enderecoIpDoCliente))
            cliente.daemon = True
            clienteThread.append(cliente)
            cliente.start()


accept = threading.Thread(target=acceptConnection, args=())
accept.start()

while True:
    signal.signal(signal.SIGINT, signal_handler)
    if fechada:
        accept.join()
        sys.exit(0)












    
  • The ctrl + c will kill the main thread but not the "daughters". Make each daughter one daemon with, for example sua_thread.daemon = True before doing the start

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.