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))
Related
I'm trying to make a connection tester with python and made this function:
import socket as skt
import sys
def main():
try:
s = skt.socket(skt.AF_INET, skt.SOCK_STREAM, 0)
except skt.error as e:
print('A conexão falhou! :(')
print(f'Erro {e}.')
sys.exit()
print("Socket criado com sucesso!")
HostTarget = input('Digite o Host ou IP a ser conectado: ')
DoorTarget = (input('Digite a porta a ser conetcada: '))
try:
s.connect:((HostTarget, int(DoorTarget)))
print(f'Cliente conectado com sucesso no Host: {HostTarget} através da porta: {DoorTarget}.')
s.shutdown(2)
except skt.error as e:
print(f'Não foi possível se conectar ao Host: {HostTarget} através da porta: {DoorTarget}.')
print(f'Erro: {e}')
sys.exit()
if __name__ == "__main__":
main()
But when I run the test, I get the following error:
Erro: [Errno 107] Transport endpoint is not connected
An exception has occurred, use %tb to see the full traceback.
This is the client:
from socket import *
server_IP_address = '127.0.0.1'
server_Port = 60000
server_socket_address = (server_IP_address, server_Port)
socket_del_cliente = socket(AF_INET, SOCK_STREAM)
socket_del_cliente.connect(server_socket_address)
mensaje_tx = input ('Introduzca su mensaje en minúsculas: ')
socket_del_cliente.sendto(mensaje_tx.encode(), server_socket_address)
print('mensaje enviado')
mensaje_rx= conexionSocket.recv(2048)
print('Recibido del servidor: ', mensaje_rx.decode())
socket_del_cliente.close()
And this is the server:
from socket import *
server_Port = 60000
socket_del_servidor = socket(AF_INET, SOCK_STREAM)
socket_del_servidor.bind(('', server_Port))
socket_del_servidor.listen(5)
conexionSocket, clientAddress1= socket_del_servidor.accept()
print('Servidor preparado para recibir')
print(clientAddress1)
mensaje_tx, clientAddress2 = conexionSocket.recvfrom(2048) #responder a la misma direccion desde la que se ha enviado
print(clientAddress2)
print('Buen mensaje', mensaje_tx.decode())
mensaje_rx = input('Introduce una respuesta: ')
socket_del_servidor.sendto(mensaje_rx.encode(), clientAddress1)
print('Mensaje enviado', mensaje_rx)
socket_del_server.close()
if i run both the server and the client, the client is able to send a message to the server but the server is not able to send a message back
This is a simple example that you can use
server :
from socket import *
server = socket(AF_INET, SOCK_STREAM)
server.bind(("",6000))
server.listen(5)
while True:
connection,address = server.accept()
msg=connection.recv(1024)
print(msg.decode())
connection.send("Thank you".encode())
connection.close()
client :
from socket import *
so = socket(AF_INET, SOCK_STREAM)
so.connect(("127.0.0.1",6000))
so.send("hello server".encode())
print(so.recv(1024).decode())
so.close()
output :
Your mistake was that the server was not constantly waiting for the message
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")
def server():
import socket
s = socket.socket(AF_INET, SOCK_STREAM)
x = socket.gethostname()
host = socket.gethostbyname(x)
print(" server will start on host : ", host)
port = 1024
s.bind((host,port))
print("")
print(" Server done binding to host and port successfully")
print("")
print("Server is waiting for incoming connections")
print("")
s.listen(1)
conn, addr = s.accept()
print(addr, " Has connected to the server and is now online ...")
print("")
while 1:
message = input(str(">> "))
message = message.encode()
conn.send(message)
print("message has been sent...")
print("")
incoming_message = conn.recv(1024)
incoming_message = incoming_message.decode()
print(" Client : ", incoming_message)
print("")
def client():
import socket
from socket import AF_INET, SOCK_STREAM
x = socket.gethostname()
info = socket.gethostbyname(x)
print("yours user is: " + info)
s = socket.socket(AF_INET, SOCK_STREAM)
host = input(str("Please enter the hostname of the server : "))
port = 1024
s.connect((host,port))
print(" Connected to chat server")
while 1:
incoming_message = s.recv(1024)
incoming_message = incoming_message.decode()
print(" Server : ", incoming_message)
print("")
message = input(str(">> "))
message = message.encode()
s.send(message)
print("message has been sent...")
print("")
first of all i want to clarify. I don't have any deep knowledge on python, but im trying to learn while doing a project for college so lets start and thanks for your time.
I'm working with Python 3.4 on Windows 10 for the hosts and Ubuntu in an Odroid as a server.
The problem on my code is that i need to send a code like 0001 to a set of hosts of which i have their ips but when i try to close the socket it won't do it and i can't open a new one to send the code to the next host.
Client code :
[yes, it's a socket server code but when i try to connect multiple clients to one server, the code stopped on listening new connections and i couldn't "fix" it in another way]
while 1:
TCP_PORT = 5000
BUFFER_SIZE = 4 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', TCP_PORT))
s.listen(1)
s, addr = s.accept()
data = s.recv(BUFFER_SIZE)
if not data:
break
if data.decode('ascii') == '0001':
print (data.decode('ascii'))
s.shutdown(socket.SHUT_RDWR)
s.close()
Server side code:
import serial
import time
import mysql.connector
import shutil
import socket
import sys
import _thread
joined_seq = '0001'
Alerta = True
TotalClientes = True
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
seq = []
UltimaIPextraida = ''
port = 5000
while Alerta == True:
if TotalClientes == True:
cnx2 = mysql.connector.connect(connection parameters removed)
cursor2 = cnx2.cursor()
cursor2.execute("SELECT MAX(Entrada) FROM Host")
for (Entrada) in cursor2:
NoTupla = ''.join(str(v) for v in Entrada)
ValorMAX = int(NoTupla)
cursor2.close()
cnx2.close()
TotalClientes = False
if ValorMAX > 0:
print('Host Numero', ValorMAX)
cnx3 = mysql.connector.connect(connection parameters removed)
cursor3 = cnx3.cursor()
query = ("SELECT IP FROM Host WHERE entrada = '%s' " % (ValorMAX))
cursor3.execute(query)
for (IP) in cursor3:
IPextraida = ''.join(str(v) for v in IP)
cursor3.close()
cnx3.close()
#if ValorMAX == 1: #DESCOMENTAR
# Alerta = False #DESCOMENTAR
ValorMAX = ValorMAX -1
print('IP Extraida = ' + IPextraida)
print('Ultima IP Extraida = '+ UltimaIPextraida)
if UltimaIPextraida == IPextraida:
print('Ultima IP extraida es identica a la nueva ip extraida, pasando a la siguiente')
elif UltimaIPextraida != IPextraida:
try:
s.connect((IPextraida, port))
s.send(joined_seq.encode('ascii'))
s.shutdown(s.SHUT_RDWR)
s.close()
print('Mensaje enviado correctamente = ' + joined_seq)
except:
print('No se pudo conectar con host')
UltimaIPextraida = IPextraida
** some code was ommited because it has no relevance **
With the mysql query i get the total of ip entries on the table and then with that i get all ip one by one to make the socket connection.
I really hope someone can help me to solve this problem... i've been 2 days trying and i'm running out of time to finish the code and it isn't the main part of the project, i only need a functional code to show some capabilities of the arduino functions graphically.
thank you all for your time and sorry for the gramatical errors and the code in spanish :(
Solved with this:
def enviaMensaje(ipdelwn):
enviado=False
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.connect((ipdelwn, port))
s.send(joined_seq.encode('ascii'))
s.close()
print('Mensaje enviado correctamente = ' + joined_seq)
enviado=True
except:
print('No se pudo conectar con host')
return enviado