Difficulty with socket.recv ()

2

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 can not visualize, maybe because of lack of experience is because the code stops on the line:

data = obj.recv(2)

By not letting the code move forward in the process call, is stopped here:

process = multiprocessing.Process(target=le_dados(s))

So I do not let my Gui come in after that.

Just complementing, it follows the rest of the code, it's used to connect to devices where I'll send and receive commands, with one working, 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()
    
asked by anonymous 24.10.2016 / 15:50

1 answer

0

Because the connection will be made to multiple servers (devices) continuously, you will need to create a socket for each of the servers.

The recv function can be configured to work in modes: "lock" until you receive some data, not block 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 by moving all of the looping for i in range (len(dados_dis)): code to a new process and leaving the connection set to "block" .

Each process will open a (different) connection to a device and treat the data independently.

Here's just a code, modified by 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 para 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()


Notes:

  • Because multiprocessing is used for communication with devices ( IO ), there may be an advantage in using Threads instead of Process .

  • The code within the process (s) updates global variables ( status_central and on_off_disp ), so you may need to check for condition .

  • 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 loop while True: within the recebe_dados() . I believe this situation needs to be addressed too.

25.10.2016 / 22:29