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