-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmainPython.py
151 lines (131 loc) · 6.87 KB
/
mainPython.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
Programa principal responsável por executar a aplicação desktop Python. Ela serve para autenticar no banco de dados o acesso recebido do Arduino além de gravar o registro do mesmo.
Autor: Roberto Higor Matos dos Anjos
"""
import serial, socket, time, select, queue
from UsuarioDao import UsuarioDao
from Usuario import Usuario
"""
Variáveis
"""
IP = "192.168.4.23" #Ip do servidor. "" significa todos os ips do computador (local e de rede)
PORTA = 65432 #Portas não registradas > 1023
TIMEOUT = 900 #Tempo esperando por dados
"""
Métodos=================================
"""
#Checar se o usuário existe e possui permissão da sala atual. A variável S é o pacote no Select
def checarSenhaPorta(s, senha, sala):
usr = UsuarioDao()
try:
if (usr.usuarioExiste(senha, sala)):
message_queues[s].put('S'.encode())
print("Sucesso na sala {}".format(sala))
else:
message_queues[s].put('F'.encode())
print("Falha na sala {}".format(sala))
except Exception as err:
print("Ocorreu um erro no envio da mensagem no método checarSenhaPorta()", err)
"""
Main ====================================
"""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Serve para criar um socket non-blocking, não bloqueando o sistema e permitindo mais de um cliente.
server.setblocking(0)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #Permitir reutilizar um socket aberto
server.bind(('localhost', PORTA))
print("Bind no IP: {} e PORTA: {}".format(IP, PORTA))
print("Servidor ouvindo...")
server.listen(20) #Numero de conexões aceitas
inputs = [server] #São os sockets onde será lido os dados
outputs = []#São os sockets em será escrito
message_queues = {}# Dicionario de mensagens
while(1):
# Bloco para tratar erro nos digitos recebidos ao invés de parar o programa
if inputs:
readable, writable, exceptional = select.select(inputs, outputs, inputs)
#
# Lidar com os sockets que enviaram dados
#
for s in readable:
# Se o socket em input for um server, significa então que chegou um novo cliente.
# Deve-se abrir uma nova conexão com o accept()
if s is server:
connection, client_address = s.accept()
print("Nova conexão de {}".format(client_address))
# Deixando a conexão como non-blocking para não suspender o sistema
connection.setblocking(0)
# Adiciona o novo cliente para a lista de inputs e cria uma fila de mensagens
inputs.append(connection)
message_queues[connection] = queue.Queue()
# Senão, significa que é um cliente existente que possui dados
else:
try:
# @@@@@@@@ Testar se precisa do send b'1' para checar conexão
data = s.recv(7).decode("UTF-8") #decode serve para transformar em caracteres e o :-2 significa ir até -2 para cortar \n
senha = int(data[1:])
sala = data[:1]
if data:
print("Recebido {} de {}".format(data, s.getpeername()))
# Autenticar a snah recebida
try:
checarSenhaPorta(s, senha, sala)
except OSError as err:
print("Ocorreu um erro com o Socket", err)
except Exception as err:
print("Ocorreu um erro ao tentar checarSenhaPorta: '", err )
# Adicionar em outputs para ser escrito posteriormente (writable)
if s not in outputs:
outputs.append(s)
# Um socket readable sem dados significa que o cliente se desconectou
else:
# Interpretar um resultado vazio como uma conxão fechada
print("Fechando {} após ler dados vazios".format(client_address))
# Remover então de outputs caso exista e em seguida de inputs
if s in outputs:
outputs.remove(s)
inputs.remove(s)
# Após removido do Array do select, pode-se fechar a conexão e remover as mensagens
s.close()
del message_queues[s]
except socket.timeout as err:
print("Sem dados recebidos: ", err)
except socket.error as err:
# O programa trava em caso de erro no Socket.
# O erro então é tratado nesse exception que faz a mesma tarefa do exceptional
# Removendo o socket das listas e o fechando
print("Erro na conexão ao receber os dados: ", err)
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
except ValueError as err:
senha = 0
print("Ocorreu um erro com digitos recebidos: '", err)
except Exception as err:
senha = 0
print("Ocorreu um erro com digitos recebidos: '", err)
#
#Pega as mensagens pendentes e as escreve no socket
#
for s in writable:
try:
next_msg = message_queues[s].get_nowait()
#Caso ocorra algum erro, ele será removido da lista de sockets.
except queue.Empty:
# Não há mais mensagens na fila. Remover da lista de Writable.
print("Fila output do {} está vazia".format(s.getpeername()))
outputs.remove(s)
else:
print("Enviando {} para {}".format(next_msg, s.getpeername()))
s.send(next_msg)
# Quando há algum erro com o socket
for s in exceptional:
print("Tratando exception de {}".format(s.getpeername()))
# Parar de esperar inputs na conexão
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
# Remover fila de mensagens
del message_queues[s]