Question:
I'm having continuity problems in my code after a function call, related to receiving data via socket with the following code:
def le_dados(obj):
lista_rcv = []
while True:
data = obj.recv(2)
if data:
lista_rcv.append(data)
if len(lista_rcv) == 4:
lista_rcv.append(obj.getpeername())
global status_central
status_central = lista_rcv
lista_rcv = []
sleep(0.25)
This function is called inside another function like this:
process = multiprocessing.Process(target=le_dados(s))
process.daemon = True
process.start()
What I'm not able to see, maybe due to lack of experience, is because the code stops on the line:
data = obj.recv(2)
Not letting the code go forward in the process
call, it is stopped here:
process = multiprocessing.Process(target=le_dados(s))
not letting me be my Bill that comes after that.
Just complementing, the rest of the code follows, it is used to connect to devices where I will send and receive commands, with just one it worked, but when I try with several I'm not getting it.
import socket
import os
import Gcomn
from time import sleep
import multiprocessing
PORT = 7557
status_central = []
on_off_disp = []
def conecta_dispositivos():
sql = 'select nome_disp, Ip_disp from dispositivos'
dados_dis = Gcomn.le_dados(sql)
global on_off_disp
on_off_disp = []
for i in range (len(dados_dis)):
try:
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#s.settimeout(5)
s.connect((dados_dis[i][1] ,7557))
if s:
print("Conectado a: ", s.getpeername())
sleep (1.5)
sendData()
on_off_disp.append(1)
print('vou chamar o process')
process = multiprocessing.Process(target=recebe_dados(s))
process.daemon = True
process.start()
print('depois do process')
except socket.error:
print ('Erro ao conectar em: ', dados_dis[i][0])
on_off_disp.append(0)
def recebe_dados(obj):
lista_rcv = []
obj.setblocking(False)
while True:
data = obj.recv(2)
if data:
lista_rcv.append(data)
if len(lista_rcv) == 4:
lista_rcv.append(obj.getpeername())
global status_central
status_central = lista_rcv
lista_rcv = []
else:
print('não recebi nada')
sleep(0.25)
def sendData(comando = 'A00000'):
s.send(comando.encode('utf-8'))
conecta_dispositivos()
Answer:
As the connection will be made to several servers (devices) continuously, it will be necessary to create a socket for each one of the servers.
The recv
function can be configured to work in modes: "lock" until receiving some data, unblock or block after a timeout .
The configuration you will use depends a lot on how you want the program to work (algorithm).
As your code uses multiprocessing, a possible strategy is to create a process for each client, moving all the looping code for i in range (len(dados_dis)):
to a new process and leaving the connection configured as "block".
Each process will open a (different) connection with a device and handle the data independently.
Here, just as an example, your code modified with this change:
import socket
import os
import Gcomn
from time import sleep
import multiprocessing
PORT = 7557
status_central = []
on_off_disp = []
# Acrescentei o parâmetro: s (socket)
def sendData(s, comando = 'A00000'):
s.send(comando.encode('utf-8'))
# Recebe os dados de 1 dispositivo no modo "bloqueio"
def recebe_dados(obj):
lista_rcv = []
while True:
# Aqui, a conexão pode ser do tipo "bloqueio"
data = obj.recv(2)
if data:
lista_rcv.append(data)
if len(lista_rcv) == 4:
lista_rcv.append(obj.getpeername())
global status_central
status_central = lista_rcv
lista_rcv = []
else:
print('não recebi nada')
sleep(0.25)
# Abre a conexão e mantém a comunicação com 1 dispositivo
def disp_interno(d):
try:
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((d[1] ,7557))
if s:
print("Conectado a: ", s.getpeername())
sleep (1.5)
sendData(s)
on_off_disp.append(1)
recebe_dados(s)
except socket.error:
print ('Erro ao conectar em: ', dados_dis[i][0])
on_off_disp.append(0)
# Cria um processo diferente para cada dispositivo
def conecta_dispositivos():
sql = 'select nome_disp, Ip_disp from dispositivos'
dados_dis = Gcomn.le_dados(sql)
global on_off_disp
on_off_disp = []
for i in range(len(dados_dis)):
print('vou chamar o process')
# Alterado para criar o processo, chamando a função: disp_interno
# Envia como parâmetro os dados da conexão
process = multiprocessing.Process(target=disp_interno, args=(dados_dis[i],))
process.daemon = True
process.start()
print('depois do process')
# o join() aguarda a finalização dos processos
for process in multiprocessing.active_children():
process.join()
if __name__=="__main__":
conecta_dispositivos()
Comments:
-
As multiprocessing is used for communication with devices ( IO ), maybe there is an advantage in using Threads instead of Process .
-
The code inside the process(es) updates global variables (
status_central
andon_off_disp
), so you may need to check whether or not there will berace condition problems. -
If a problem occurs in one of the connections (the remote device closes the connection, network instability, etc.), the process responsible for this connection will "die" in the
while True:
loopingwhile True:
inside therecebe_dados()
function. I believe this situation needs to be addressed as well.