def threadSocket(Socket, port):
'''
Thread encargado de sotener comunicacion entre Socket cliente y
el puerto serial asignado
Mientras se mantenga activo el thread de recepcion se intentara leer del
puerto serial y enviarlo al socket cliente
Se asume que socket y port son objetos vaidos validos
'''
#Intenta abrir el puerto serial
try:
COM = serial.Serial(port-1)
except:
#Si esta en uso no se encuentra disponible, muestra error
print 'Error: Puerto COM'+str(port)+' no disponible'
else:
#Al conectarse se crea el thread de recepcion
print 'Conectado a puerto COM'+str(port)
rxThread = threading.Thread(target=rxThreadDef,args=(Socket,COM))
rxThread.start()
dato = ''
#Mientras el thread este activo
while rxThread.isAlive():
try:
#Lee del puerto serial y envia a Socket cliente
dato += COM.read()
if parserCOMToSocket(dato):
Socket.send(dato)
dato=''
except:
break
print "Puerto cerrado!"
#Cierra puerto Serial
COM.close()
#Cierra Socket
Socket.close()
#print "Hilo terminado"
def rxThreadDef(Socket,COM):
'''
Thread (Hilo) encargado de recibir la informacion del Cliente
y enviarla por medio del puerto serial
Si se genera algun error se rompe el ciclo y termina el thread
'''
dato = ''
while 1:
try:
d = Socket.recv(1024)
except:
break
if d:
dato += d
if parserSocketToCOM(dato):
COM.write(dato)
print dato
dato = ''
else:
break
def parserSocketToCOM(dato):
return True
def parserCOMToSocket(dato):
return True
Hi, I try to implement a bridge between a serial port and a AIR application using sockets in Python 2.7
When the rxThread die, the socketThread will be able to close the socket and the serial Port because the client socket is die. But the script need to wait for a read from the serial port before close all.
If I try with a timeout=0, the CPU usage grow to 100%. If I try with a timeout=None but use COM.isWaiting(), I will get the same problem (100% of CPU)
How can I know if a socket is closed in other way?
If you need to read from two sources, you can do it happily with select(). You won't need threads in that case. select blocks until one or more of the resources is available, and then returns the set of resources available, so you can react on each. Note that select works with file descriptors and you may need to put it in nonblocking mode.
Related
In the frame of our course, our teacher asked us to write a client-server program, where the server split two matrices that it wants to multiply then send them to the client and the client should calculate their part of the result and send it back to the server.
I succeed to divide the matrix and send it to clients but my problem is that my client cannot send back the results to the server. When I try to receive any message at the server-side, my client no longer receives the matrix to compute.
Here is my server code
!/usr/bin/env python
# -*- coding: utf-8 -*-
from socket import socket, AF_INET, SOCK_STREAM, timeout
from threading import Thread
import numpy as np
import pickle
buf = 4096
class ErrorLevels:
OK = "OK"
ERROR = "ERREUR"
class Server(Thread):
def __init__(self):
Thread.__init__(self)
self.socket = socket(AF_INET, SOCK_STREAM)
self.socket.bind(("localhost", 2020))
self.socket.settimeout(0.5)
self.running = False
self.client_pool = []
def client_handling_stopped(self, client, error_level, error_msg):
print("Le gerant de {} s'est arrete avec le niveau d'erreur {} ({})".format(client.address[0],error_level,error_msg))
self.clean_up()
# self.log_connection_amount()
def log_connection_amount(self):
print("Il y a maintenant {} client(s) connecte(s)".format(len(self.client_pool)))
def stop(self):
print("Arrêt du serveur")
for client in self.client_pool:
client.close_connection()
self.running = False
def clean_up(self):
"""
Enleve tous les gérants de clients innactifs de la liste des gerants de clients
"""
self.client_pool = [client for client in self.client_pool if client.alive]
#le serveur genere le calcul a envoyer aux clients
#generation de matrices
def matrice_aleatoire(self,intervalle, ligne, colonne):
matrice = np.random.randint(intervalle, size=(ligne, colonne))
return matrice
def run(self):
A = self.matrice_aleatoire(10,100,100)
B = self.matrice_aleatoire(10,100,100)
#code fonctionnnant pour 10 clients
#division de A en 10 sous matrices de 10 lignes et envoie aux clients
C = np.vsplit(A, 10)
#dictionnaire a envoyer a chaque client
data = []
for i in range(10):
dic = {'num':i,'partA':C[i],'partB':B}
data.append(dic)
print("Démarrage du serveur\nAttente des connexions clients...")
self.running = True
self.socket.listen(5)
i=-1
while self.running:
try:
client, address = self.socket.accept()
i=i+1
except timeout:
continue # on retourne au début de la boucle jusqu'à avoir un client
print("Connexion depuis {}".format(address))
#envoie et reception du calcul aux clients connnectes
#actuellement 10 clients
client_handling = ClientHandling(client, address,data[i], self.client_handling_stopped)
self.client_pool.append(client_handling)
client_handling.start()
# self.log_connection_amount()
#classe d'ojbets thread pour gerer les connections clients
class ClientHandling(Thread):
def __init__(self, client, address,data, exit_callback):
Thread.__init__(self)
self.client = client
self.address = address
self.data = data
self.exit_callback = exit_callback # une fonction qui devra être appelée lorsque cet objet sera devenu inactif
self.alive = True
def _stop(self, error_level, error_msg):
self.alive = False
self.close_connection()
self.exit_callback(self, error_level, error_msg)
def close_connection(self):
self.alive = False
self.client.close()
print("Fin de la communication avec {}".format(self.address))
def run(self):
try:
#envoie du calcul
print("debut envoie du calcul")
data_string = pickle.dumps(self.data)
self.client.sendall(data_string)
print("fin envoie")
#reception resultat
'''
here is the problem when i try to receive the result
pick_ = b''
while 1:
dat = self.client.recv(buf)
pick_ += dat
print("reception resultat")
if not dat:break
res = pickle.loads(dat)
print("fin reception")
# print(res)'''
#quelques exceptions possibles
except ZeroDivisionError:
self._stop(ErrorLevels.ERROR, "Une division par zero tente")
except ConnectionAbortedError:
if self.alive: # innatendu
self._stop(ErrorLevels.ERROR, "La connexion abandonnee")
else: # on est dans le cas où le gérant est volontairement arrêté
return # on arrête donc tout, plus besoin de faire quoi que ce soit
self._stop(ErrorLevels.OK, "Le client a ferme la connection")
try:
#lancement du thread serveur
server = Server()
server.start()
while True: continue
except KeyboardInterrupt:
server.stop()
server.join()
here is my client.py
import socket
from threading import Thread
#import numpy as np
import pickle
hote = "localhost"
port = 2020
buf = 4096
connexion_avec_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_avec_serveur.connect((hote, port))
print("Connexion établie avec le serveur sur le port {}".format(port))
#thread pour le calcul du client
class Calcul(Thread):
def __init__(self):
Thread.__init__(self)
#fonction qui extrait les donnees et multiplie
def multmat(self,data):
num = data['num']
A = data['partA']
B = data['partB']
C = A # B
resul = {'num':num,'partC':C}
return resul
def run(self):
#reception calcul
pick_str = b''
while 1:
data = connexion_avec_serveur.recv(buf)
pick_str += data
if not data:break
#connexion_avec_serveur.close()
dic = pickle.loads(pick_str)
#print(dic)
#calcul du produit
res = self.multmat(dic)
print(res)
#envoie du resultat du calcul
data_string = pickle.dumps(res)
connexion_avec_serveur.sendall(data_string)
cal = Calcul()
cal.start()
cal.join()
connexion_avec_serveur.close()
The main problem is that the client does not know when the complete message from the server has been received. The receiving code expects the server to close the connection before it can process the incoming data. However, the server can not close the connection because it is waiting for the client to send a response over the same connection.
The client is blocked at data = connexion_avec_serveur.recv(buf) until the server closes the connection, or some other network event occurs that severs that connection. Meanwhile the server is also blocked at dat = self.client.recv(buf) awaiting a response from the client - there is a deadlock.
The solution is to arrange for the client to know when it has received the complete message from the server, which means adding some protocol. One way is for the sever to append a sentinel value to signal the end of the message, and for the client to watch for that sentinel. Another way is for the server to prepend to the message the length of the payload, in this case the length of the pickled data, which I show here.
For the client change the run() function:
import struct
def run(self):
# First 4 bytes are the length of the payload
data = connexion_avec_serveur.recv(4)
msglen = struct.unpack('!L', data)[0]
print(f'Length of payload {msglen = }')
payload = []
while msglen > 0:
print(f'{msglen = } calling recv...')
data = connexion_avec_serveur.recv(buf)
print(f'received {len(data)} bytes')
payload.append(data)
msglen -= len(data)
print(f'total bytes read {sum(len(s) for s in payload)}')
dic = pickle.loads(b''.join(payload))
#print(dic)
#calcul du produit
res = self.multmat(dic)
print(res)
#envoie du resultat du calcul
data_string = pickle.dumps(res)
connexion_avec_serveur.sendall(data_string)
And for the server:
import struct
def run(self):
try:
#envoie du calcul
print("debut envoie du calcul")
data = pickle.dumps(self.data)
# prepend message with length of the pickled data
msg = struct.pack(f'!L{len(data)}s', len(data), data)
print(f'sending {len(msg)} bytes to client')
self.client.sendall(msg)
print("fin envoie")
#reception resultat
pick_ = b''
while True:
print('calling recv()')
dat = self.client.recv(buf)
print(f'recv() returned {len(dat)} bytes')
pick_ += dat
print("reception resultat")
if not dat:
break
res = pickle.loads(pick_)
print(f'{res = }')
print("fin reception")
#quelques exceptions possibles
except ZeroDivisionError:
self._stop(ErrorLevels.ERROR, "Une division par zero tente")
except ConnectionAbortedError:
if self.alive: # innatendu
self._stop(ErrorLevels.ERROR, "La connexion abandonnee")
else: # on est dans le cas où le gérant est volontairement arrêté
return # on arrête donc tout, plus besoin de faire quoi que ce soit
self._stop(ErrorLevels.OK, "Le client a ferme la connection")
I have a code in python to communicate between two virtuals machines.
But I have an error. Connexion refused. are there any problems with the port that I use?
I don't think there is any firewall or anything.
thanks a lot
Here is my code below :
import socket
import subprocess
try:
# on cree un objet socket
# socket.AF_INET : la famille d adresses, ici ce sont des adresses Internet ;
# socket.SOCK_STREAM : le type du socket, SOCK_STREAM pour le protocole TCP.
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# on defini le port
port = 12345
# connection vers le serveur
s.connect(('192.168.1.20', port))
# receive data from the server, 2048 bytes
print s.recv(2048)
# close the connection
s.close()
except:
print("une erreur est survenue...")
and then the code of my other machine
import socket
import subprocess
import os,sys
#==========================================================================================
#creation d'une classe pour rendre le programme oriente objet
class GetInfo:
infos = os.uname()
currentUser = os.getlogin()
rep_actuel = os.getcwd()
myDirectory = os.listdir("/home/debian/Documents")
scanpath = "Liste de tous les repertoires dans Users : \n"
def listInfo(self):
#afficher des informations sur le systeme
return GetInfo.infos
#afficher l'utilisateur actuel
return GetInfo.currentUser
#afficher le path du repertoire actuel
return GetInfo.rep_actuel
def scan(self):
#print "Liste de tous les repertoires dans Users/"
#on liste toutes les directories et sous directories
for file in GetInfo.myDirectory:
GetInfo.scanpath += file + "; \n"
return GetInfo.scanpath
#instance de l objet GetInfo (creation de l'objet)
GetMyInfo = GetInfo()
# afficage des infos de l'objet
#GetMyInfo.listInfo()
#GetMyInfo.scan()
#==========================================================================================
# on cree un objet socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print "Socket successfully created"
# reservation d'un port specifique
port = 12345
# contient le nom d hote et le numero du port
#identifiant le serveur auquel on veut se connecter.
s.bind(('192.168.1.15', port))
print "socket binded to %s" %(port)
# activation du mode ecoute
# avec un nombre maximum de connexions qu il peut recevoir sur ce port sans les accepter
s.listen(5)
print "socket is listening"
GetMyInfo.scan()
#==========================================================================================
# gestion des erreurs
while True:
# on etabli la connection avec le client
client, addr = s.accept()
print 'Got connection from', addr
#client.send("Liste de tous les repertoires dans Users/")
# send the informations about the victim.
client.send(GetMyInfo.scan())
print client.recvfrom(2048)
# on ferme la connection
s.close()
the error says Connexion refused here is the error below
error
Looks like you are connecting the client to one address:
# connection vers le serveur
s.connect(('192.168.1.20', port)) # <-- **.20**
But the server is listening on another:
# contient le nom d hote et le numero du port
#identifiant le serveur auquel on veut se connecter.
s.bind(('192.168.1.15', port)) # <-- **.15**
I have a problem when I send data from client to server in python INET Stream socket.
I send a dictionary using library json of python , and , in the server side, I create a Ticket object and save in my MySQL DB.
At this point, the program don't have any problems, but, when i try save other ticket in the same ejecution of client, the server not recieve the data and , the ticket don't save in the DB. Any solutions?
In server.py
def thread_fuction(port,sock):
while True:
msg = clientsocket.recv(1024)
print(f"Recibido del puerto {port} atendido por PID {os.getpid()}: {msg.decode()}")
logger(sock,msg)
if (msg.decode() == 'INSERTAR'):
dict_data=sock.recv(1024).decode()
final_data=json.loads(dict_data)
final_data=dict(final_data)
for key,value in final_data.items():
if key == "autor":
autor=value
elif key == "titulo":
titulo=value
elif key == "descripcion":
descripcion=value
elif key == "estado":
estado=value
print(final_data)
ticket=Ticket(autor=autor,titulo=titulo,descripcion=descripcion,estado=estado,fecha=datetime.now())
session.add(ticket)
session.commit()
break
# creamos el objeto socket
try:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Fallo al crear el socket!')
sys.exit()
#Establecemos parametros
host = "localhost"
port = int(8070)
# Blindeamos el puerto y el host
serversocket.bind((host, port))
# Establecemos 5 peticiones de escucha como maximo.
serversocket.listen(5)
if __name__ == "__main__":
while True:
# establish a connection
clientsocket, addr = serversocket.accept()
print('Conexion establecida: SERVER ON')
conection=Thread(target=thread_fuction,args=(port,clientsocket))
conection.start()
In client.py
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Creado!")
except socket.error:
print ('Fallo al crear el socket!')
sys.exit()
host = "localhost"
port = int(8070)
client_socket.connect((host, port))
print ('Socket conectado al host', host, 'en el puerto', port)
while True:
print("""\n
\t\t\t *** Menu ***
- INSERTAR TICKET (INSERTAR)
- SALIR (SALIR)
""")
opcion = input('Opcion: ').upper()
client_socket.sendto(opcion.encode(), (host, port))
if (opcion == 'INSERTAR'):
autor = input("\nIngrese autor del Ticket: ")
titulo = input("\nIngrese titulo del ticket: ")
descripcion = input("\nIngrese descripcion del ticket: ")
estado = input("\nIngrese estado del ticket (pendiente, en procesamiento o resuelto): ")
while validar_estado(estado):
estado=input("Estado debe ser uno de los pedidos, intentelo nuevamente): ")
data={"autor":autor,"titulo":titulo,"descripcion":descripcion,"estado":estado}
json_data=json.dumps(data) #Convertimos el diccionario a JSON
client_socket.sendto(json_data.encode(),(host,port))
I have the code below:
import urllib.request
import json
flag_servidor = 0
flag_salva_txt = 0
numero = 0
#codigo para verificar se há conexao como servidor e caso nao
#haja ele criar um arquivo txt com as infos
while 1:
try:
url = urllib.request.urlopen('http://IP/CAMINHO/get_infos.php')
x_ = url.read()
y_ = json.loads(x_.decode('utf-8'))
get_turno_ = y_["turno"]
print(get_turno_)
#salva as infos do txt dentro do banco de dados
if flag_salva_txt == 1: #significa que temos infos para serem salvas
arquivo = open('novo-arquivo1.txt', 'r')
for linha in arquivo:
linha = linha.rstrip()
valor = linha.split(";")
print(valor[0])
flag_salva_txt = 0
continue
except Exception as e:
print("Servidor indisponível.Erro:", e)
if flag_salva_txt == 0:
#após salvar txt
flag_salva_txt = 1
numero = numero +1
arquivo = open('novo-arquivo'+str(numero)+'.txt', 'w')
arquivo.write('nova linha;123;1pop' + '\n')
arquivo.close()
continue
The problem is that: when an exception happened for the first time it shows me message error but when it happens for second time my code stop running and doesn´t show anything.
I'm still not quite crystal clear about what your program is supposed to do, but maybe something like this helps.
I refactored your program to a separate function to get the data, and printing it out (or whatever you like to do) is in the main loop.
In addition, to not hit the server as fast as your script can, there's a delay of 5 seconds between every request, successful or not.
import datetime
import time
import urllib.request
import json
def get_turno():
url = urllib.request.urlopen("http://IP/CAMINHO/get_infos.php")
data = json.loads(url.read().decode("utf-8"))
return data["turno"]
while True:
try:
turno = get_turno()
except Exception as exc:
print("Retrieving turno data failed: {}".format(exc))
else:
current_time = datetime.datetime.now().isoformat()
print("Time: {} - Turno: {}".format(current_time, turno))
time.sleep(5)
I was a socket TCP server in python using asyncore. My handle_read function is:
def handle_read(self):
data = self.recv(50)
'''interpretar os comandos:
operação: Ligar/Desligar Bomba, Ligar/Desligar Aquecedor, Alterar velocidade da bomba
Modo: trocar de modo automático para remoto
Armazenamento: ativar ou desativar o armazenamento de dados para o trend e
também apagar dados
'''
if len(data) < 2: #comandos digitais
try:
process_commands(data)
except Exception as err:
print(str(err))
else: #comando analogico
try:
ld = json.loads(data.decode('utf-8'))
bytescommand = pack('f',ld['pump_speed'])
bus.write_block_data(arduinoAddress,53,list(bytescommand))
except Exception as err:
print(str(err))
finally:
pass
Look, i test the data received to execute functions. But when a client disconnect, the program returns:
"char format requires a bytes object of lenght 1"
This indicates that handle_read function executes when client disconnect.
It's normal? How i proccess the situation?
Thanks a lot!
That is a normal call. When the peer closes its socket (or simply shutdowns it with SH_WR) a read call returns immediately with 0 bytes.
So your handle_read should be prepared for that end of file on the socket:
def handle_read(self):
...
if len(data) == 0: # EOF on input socket
pass # or add disconnection processing...
elif len(data) < 2: #comandos digitais
...