0

I'm begineer in sockets and I've make an app in model Multiclient-Server what about uses socket TCP in Python and works like one specific client send some message to server and the server send the message for the clients who just listen (so, I'm not using multithreading in Server because I don't need the other clients sending something between then). But, I'm with some problems, but most notable is errno 104 - Connection reset by peer.

I've changed a lot of Server code because of this problem, but this keeping happen always ... In first time, I thought about the clients lost the connection because the clients was in state idle for a long time and the connection was ended. So, I've implemented Keep Alive for the clients and the server, but this didn't solve. And this time, I improvised a Keep Alive about clients always sending "1" for the server to connection don't be idle, but this didn't resolved again because I'm keeping lost a lot of connections with this same error and I don't now how to fix this.

Somebody can help me? pls? And if the answer is no, someone knows a easy way to make an app like this (like a framework, etc)? :(

Edit:

Server code:

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.setblocking(0)
server.bind(('', 10552))
server.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 4096)
while True:
    logging.info('Começando processo...')
    try:
        while inputs:
            msg = ''
            readable, writable, exceptional = select.select(inputs, outputs, inputs)
            for s in readable:
                if s is server:
                    try:
                        connection, client_address = s.accept()
                        logging.info('Nova conexão! {}:{}'.format(client_address[0], client_address[1]))
                        connection.setblocking(0)
                        if horario > agora() and sinal:
                            logging.info('Enviando o ultimo sinal \"{}\" para {}.'.format(sinal.decode(), client_address[0]))
                            connection.sendall(sinal)
                        else:
                            pass
                        inputs.append(connection)
                    except Exception as e:
                        logging.error('Erro durante o processo de aceitação do servidor. Motivo {}'.format(e))
                        continue
                else:
                    try:
                        data = s.recv(1024)
                        if data:
                            if data.decode() == '1':
                                if s not in outputs:
                                    outputs.append(s)
                                    continue
                            elif not str(data.decode()).isdigit():
                                logging.debug('Mensagem detectada: {}'.format(data.decode()))
                                if s != gerenciador:
                                    gerenciador = s
                                if data.decode() == 'online' and not 'msg' in data.decode():
                                    logging.info('Enviando \"{}\" de volta'.format((len(outputs))))
                                    s.sendall(str.encode(str(len(outputs))))
                                    continue
                                elif data.decode() == 'ping':
                                    logging.info("Devolvendo \"pong\".")
                                    s.sendall(str.encode("pong"))
                                    continue
                                else:
                                    if 'sinal' in data.decode() and not 'msg' in data.decode():
                                        logging.debug("Memorizando sinal")
                                        dados = str(data.decode()).replace('sinal ', '')
                                        dados = dados.split(',')
                                        if len(dados) != 5:
                                            logging.debug('Sinal inválido')
                                            dados = ''
                                            continue
                                        horario = datetime.strptime(str(dados[0] + ':00'), '%H:%M:%S')
                                        horario = datetime.strftime((horario - timedelta(seconds = 30)), '%H:%M:%S')
                                        sinal = data
                                        logging.debug("Sinal memorizado!")
                                    elif 'cancelar' in data.decode() and not 'msg' in data.decode():
                                        if sinal:
                                            sinal = ''
                                            dados = ''
                                            logging.debug('Sinal apagado da memória.')
                                        else:
                                            pass
                                    else:
                                        pass
                                msg = data
                            else:
                                pass
                        else:
                            inputs.remove(s)
                    except socket.error as e:
                        logging.warning('Exceção detectada no processo de manter conexão viva. Motivo: {}'.format(e))
                        if s in inputs:
                            inputs.remove(s)
                            continue

            if msg:
                logging.debug('Començando processo de envio de \"{}\"'.format(msg.decode()))

            for s in writable:
                try:
                    if msg:
                        s.sendall(msg)
                        cont += 1
                    else:
                        continue
                except socket.error as e:
                    logging.warning('Exceção detectada na hora do envio. Motivo: {}'.format(e))
                    outputs.remove(s)

            if msg:
                logging.debug('Alcançou {} de {}.'.format(cont, len(outputs)))
                logging.debug('Enviando \"{}\" para o Gerenciador.'.format(msg.decode()))
                try:
                    gerenciador.sendall(msg)
                except Exception as e:
                    logging.warning('Exceção detectada durante o retorno para gerenciador. Motivo: {}'.format(e))
                cont = 0

            for s in exceptional:
                try:
                    inputs.remove(s)
                    if s in outputs:
                        outputs.remove(s)
                    s.close()
                except:
                    pass
    except:
        logging.error('EXCEÇÃO CRÍTICA - Tentando reiniciar processo')
        continue

Client part of connection code:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 9000, 3000))
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 4096)
servidor = (ip, porta)
s.connect(servidor)
s.setblocking(0)
s.settimeout(1)
while True:
        time.sleep(0.4)
        try:
            s.sendall(str.encode('1'))
            data = s.recv(1024)
            if data.decode() == anterior:
                time.sleep(1)
                continue
            else:
                anterior = data.decode()
            if data.decode() == 'cancelar':
                cancel = True
            elif 'msg' in data.decode():
                msgem = data.decode()
                msgem = msgem.replace('msg ', '')
                print(colored('=+=+=+' * 20,"yellow"))
                print(colored('Nova notificação: {}'.format(msgem), 'yellow'))
                print(colored('=+=+=+' * 20,"yellow"))
                evento.set()
            elif 'sinal' in data.decode() and not 'msg' in data.decode():
                sinal = data.decode()
                sinal = sinal.replace('sinal ', '')
                evento.set()
            elif data.decode() == 'reiniciar':
                print(colored('=+=+=+' * 20,"yellow"))
                print(colored('Processo de reinicialização de conexão com servidor requerido.\nFavor, aguarde... Este processo demorará 1 minuto\nReiniciando...',"yellow"))
                print(colored('=+=+=+' * 20,"yellow"))
                time.sleep(65)
                s.close()
                reconectar()
                print(colored('Renicialização completa.\n',"yellow"))
                print('Esperando o próximo sinal...', end = '\r', flush = True)
                continue
            elif data.decode() == 'manutencao':
                print(colored('=+=+=+' * 20,"yellow"))
                print(colored('ATENÇÃO! Os servidores Live entrarão em manutenção. Caso esteja acontecendo algum sinal, o programa será parado apenas ao término do mesmo.',"yellow"))
                print(colored('=+=+=+' * 20,"yellow"))
                s.close()
                manutencao = True
                evento.set()
                sys.exit()
            else:
                continue
        except socket.error:
            s.close()
            reconectar()
def reconectar():
    global s, parada
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 10000, 3000))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 4096)
    r = 0
    while True:
        try:
            s.connect(servidor)
            break
        except socket.error as e:
            r+=1
            print(e)
            time.sleep(2)
            continue
    if r >= 10:
        r = 0
        print('Conexão perdida com o servidor Live foi perdida.\nCaso esteja acontecendo um sinal, o programa pedirá para reiniciar após o término do sinal')
        parada = True
        input('')
        sys.exit()
    else:
        pass
Shynz0
  • 13
  • 4
  • hi, interesting, perhaps set a keep-alive value https://stackoverflow.com/questions/12248132/how-to-change-tcp-keepalive-timer-using-python-script – IronMan Jan 19 '21 at 18:03
  • @IronMan I already tried with this and doesn't work :( – Shynz0 Jan 19 '21 at 18:06
  • Since there is no code here we cannot help you with the code. Basically all what you provide is a very broad description of the what your application is doing, that you run into a specific error, that you've tried various broadly described things and that this did not help. It is impossible to find out from this what you exactly did and where your problem is and how to solve it. See [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) of what you need to provide to get better help. – Steffen Ullrich Jan 19 '21 at 18:56
  • @SteffenUllrich sorry about that, I edited now for better understanting – Shynz0 Jan 19 '21 at 20:30
  • @Shynz0: While there is now some code it is neither minimal nor reproducible (code not complete, no instructions on how to reproduce). – Steffen Ullrich Jan 19 '21 at 21:17

0 Answers0