I create a client-server model in python.
It's like a chat room, but i tried to encrypt the messages using "CTR" from cryptography.io.
When i encrypt and decrypt in the client, it work pretty well but when i sent it to the server always showing this :
> > Task exception was never retrieved
> future: <Task finished coro=<handle_echo() done, defined at Server.py:43> exception=UnicodeDecodeError('utf-8', b'\x8f.\xcb', 0,
> 1, 'invalid start byte')>
> Traceback (most recent call last):
> File "Server.py", line 53, in handle_echo
> data = srvwrk.process(data)
> File "Server.py", line 25, in process
> txt = msg.decode()
> UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8f in position 0: invalid start byte
Sorry about my english, thanks
client:
# Código baseado em https://docs.python.org/3.6/library/asyncio-stream.html#tcp-echo-client-using-streams
import asyncio
import socket
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
conn_port = 8888
max_msg_size = 9999
class Client:
""" Classe que implementa a funcionalidade de um CLIENTE. """
def __init__(self, sckt=None):
""" Construtor da classe. """
self.sckt = sckt
self.msg_cnt = 0
def process(self, msg=b""):
""" Processa uma mensagem (`bytestring`) enviada pelo SERVIDOR.
Retorna a mensagem a transmitir como resposta (`None` para
finalizar ligação) """
self.msg_cnt +=1
backend = default_backend()
key = os.urandom(32)
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=backend)
print('Received (%d): %r' % (self.msg_cnt , msg.decode()))
print('Input message to send (empty to finish)')
new_msg = input().encode()
encryptor = cipher.encryptor()
ct = encryptor.update(new_msg) + encryptor.finalize()
print(ct)
return ct if len(ct)>0 else None
#
#
# Funcionalidade Cliente/Servidor
#
# obs: não deverá ser necessário alterar o que se segue
#
#asyncio.coroutine
def tcp_echo_client(loop=None):
if loop is None:
loop = asyncio.get_event_loop()
reader, writer = yield from asyncio.open_connection('127.0.0.1',
conn_port, loop=loop)
addr = writer.get_extra_info('peername')
client = Client(addr)
msg = client.process()
while msg:
writer.write(msg)
msg = yield from reader.read(max_msg_size)
if msg :
msg = client.process(msg)
else:
break
writer.write(b'\n')
print('Socket closed!')
writer.close()
def run_client():
loop = asyncio.get_event_loop()
loop.run_until_complete(tcp_echo_client())
run_client()
This is the server :
i tried to put 'utf-8' in txt = msg.decode()... but always showing the same error
# Código baseado em https://docs.python.org/3.6/library/asyncio-stream.html#tcp-echo-client-using-streams
import asyncio
import codecs
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
conn_cnt = 0
conn_port = 8888
max_msg_size = 9999
class ServerWorker(object):
""" Classe que implementa a funcionalidade do SERVIDOR. """
def __init__(self, cnt, addr=None):
""" Construtor da classe. """
self.id = cnt
self.addr = addr
self.msg_cnt = 0
def process(self, msg):
""" Processa uma mensagem (`bytestring`) enviada pelo CLIENTE.
Retorna a mensagem a transmitir como resposta (`None` para
finalizar ligação) """
self.msg_cnt += 1
txt = msg.decode()
print(txt)
decryptor = cipher.decryptor()
ctt = decryptor.update(msg) + decryptor.finalize()
print(ctt)
print('%d : %r' % (self.id,txt))
new_msg = txt.upper().encode()
return new_msg if len(new_msg)>0 else None
#
#
# Funcionalidade Cliente/Servidor
#
# obs: não deverá ser necessário alterar o que se segue
#
#asyncio.coroutine
def handle_echo(reader, writer):
global conn_cnt
conn_cnt +=1
addr = writer.get_extra_info('peername')
srvwrk = ServerWorker(conn_cnt, addr)
data = yield from reader.read(max_msg_size)
while True:
if not data: continue
if data[:1]==b'\n': break
data = srvwrk.process(data)
if not data: break
writer.write(data)
yield from writer.drain()
data = yield from reader.read(max_msg_size)
print("[%d]" % srvwrk.id)
writer.close()
def run_server():
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_echo, '127.0.0.1', conn_port, loop=loop)
server = loop.run_until_complete(coro)
# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
print(' (type ^C to finish)\n')
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
print('\nFINISHED!')
run_server()
You seem to encode then encrypt the message but try to decode then decrypt the message. If you decrypt the message first then decode it this should solve the problem.
I think changing the decryption code to this should do the trick:
decryptor = cipher.decryptor()
ctt = decryptor.update(msg) + decryptor.finalize()
print(ctt)
txt = cct.decode()
print(txt)
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 found some code here for a project at : https://picamera.readthedocs.io/en/release-1.13/recipes2.html#rapid-capture-and-streaming section 4.9
I successfully make it work but when i tried to put the serveur on the raspberry py instead of the client, i would not work.
EDIT:
EDIT:
I found the answer : On the server the file needs to be open in write (wb) and on the client it needs to be open in read (rb)
However, we get 7 secondes of latency beteen the server and the client, Do you know how i could lower it ?
LE SERVEUR
# -*-coding:utf-8 -*
import io
import socket
import struct
from PIL import Image, ImageTk
from threading import Thread
import time
class ControleurClientVideo():
def __init__(self, controleur_client):
self.adresse='0.0.0.0'
self.port=8000
self._client_socket = socket.socket()
self._connection = None
self._thread = None
self._stop = False
def connection_raspberry(self):
self._thread = Thread(target=self._connection_avec_raspberry)
self._thread.start()
def _connection_avec_raspberry(self):
try:
self._client_socket.connect((self.adresse, self.port))
self._connection = self._client_socket.makefile('wb')
self._connection_active=True
print("Connection avec le serveur etabli")
time.sleep(2)
self._recevoir_flux_image()
except Exception as e:
print(e)
def _recevoir_flux_image(self):
try:
while not (self._stop):
# Read the length of the image as a 32-bit unsigned int. If the
# length is zero, quit the loop
image_len = struct.unpack('<L',
self._connection.read(struct.calcsize('<L')))[0]
if not image_len:
self.connection_perdu = True
break
# Construct a stream to hold the image data and read the image
# data from the connection
image_stream = io.BytesIO()
image_stream.write(self._connection.read(image_len))
# Rewind the stream, open it as an image with PIL and do some
image_stream.seek(0)
image_pill = Image.open(image_stream)
image_pill = image_pill.resize((320, 240), Image.ANTIALIAS)
image_tk = ImageTk.PhotoImage(image_pill)
print(image_tk)
self.controleur_client.changer_image(image_tk)
finally:
self.fermer_connection()
def fermer_connection(self):
self._stop = True
time.sleep(0.5)
if not (self._connection == None):
self._connection.close()
self._connection = None
self._client_socket.close()
self._client_socket=None
self._thread = None
print("Connection avec le serveur fermer")
LE CLIENT
# -*-coding:utf-8 -*
import io
import socket
import struct
import time
import picamera
from threading import Thread
class ControleurStreamingVideo():
def __init__(self):
self.adresse='0.0.0.0'
self.port=8000
self._serveur_socket = socket.socket()
self._serveur_socket.bind((self.adresse, self.port))
self._connection = None
self._thread=None
def ouvrir_serveur(self):
self._thread = Thread(target=self._connection_avec_client)
self._thread.start()
def _connection_avec_client(self):
try:
print("Serveur en attente d'une connection...")
self._serveur_socket.listen(5)
self._connection = self._serveur_socket.accept()[0].makefile('rb')
print("Connection réussi, début de la vidéo")
except Exception as e:
repr(e)
finally:
self._envoit_image()
self._serveur_socket.close()
def _envoit_image(self):
try:
self.output = SplitFrames(self._connection)
with picamera.PiCamera(resolution='VGA', framerate=30) as camera:
time.sleep(1) #warmup la caméra
camera.start_recording(self.output, format='mjpeg')
camera.wait_recording(30)
camera.stop_recording()
self._serveur_socket.close()
except Exception as e:
print(e)
class SplitFrames(object):
def __init__(self, connection):
self.connection = connection
self.stream = io.BytesIO()
def write(self, buf):
if buf.startswith(b'\xff\xd8'):
# Start of new frame; send the old one's length
# then the data
size = self.stream.tell()
if size > 0:
self.connection.write(struct.pack('<L', size))
self.connection.flush()
self.stream.seek(0)
self.connection.write(self.stream.read(size))
self.stream.seek(0)
self.stream.write(buf)
When i run the program it says only write for error. I found out that the problem come from the method write in SplitFrames. Any idea on what is causing this
SERVEUR:
Serveur en attente d'une connection...
Connection réussi, début de la vidéo
write
CLIENT:
Connection avec le serveur etabli
Connection avec le serveur fermer
read
EDIT:
I found the answer : On the server the file needs to be open in write (wb) and on the client it needs to be open in read (rb)
However, we get 7 secondes of latency beteen the server and the client, Do you know how i could lower it ?
I have a code which is running on 2 hosts. They are processing some photos. When host1 receives a message, it will send some of its photos to host2 for processing. It will also send a list to host2 (it will convert it to string and then it will send it).
import pickle
import time, threading
host = commands.getoutput("hostname -I")
port = 5005
i = 0
backlog = 5
BUFSIZE = 4096
queueList = []
start = []
end = []
l = threading.Lock()
def read_udp(s):
data,addr = s.recvfrom(1024)
global start
if data.startswith('10.0.0'):
print("received message:", data)
data_split = data.split(" ")
address = data_split[0]
num = int(data_split[1])
ipToTransfer = address
l.acquire()
transferList = queueList[-num:]
del queueList[-num:]
transferStart = start[-num:]
del start[-num:]
l.release()
msg = pickle.dumps(transferStart)
#udp_send('New Transfer', ipToTransfer)
udp_send(msg, ipToTransfer)
send_file(ipToTransfer, transferList)
else:
recvStart = pickle.loads(data)
print("start before add::: ", start)
print("received::: ", recvStart)
l.acquire()
start = start + recvStart
l.release()
print("start after add::: ", start)
def udp_send(s, ip):
UDP_IP = ip
if(type(s) == str):
MESSAGE = s
else:
MESSAGE = pickle.dumps(s)
#print(MESSAGE)
print ("UDP target IP & port:", UDP_IP, port)
print ("message:", MESSAGE)
sock3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock3.sendto(MESSAGE, (UDP_IP, port))
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def send(sock2, data2):
while data2:
sent = sock2.send(data2)
data2 = data2[sent:]
def send_file(ipToTransfer, transferList):
while transferList:
fname = transferList.pop(0)
print("transferring:", fname)
with open(fname, 'rb') as f:
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock2.connect((ipToTransfer, 5005))
except socket.error as err:
print(err, ipToTransfer, 5005)
sock2.close()
return
# Send the file name length & the filename itself in one packet
send(sock2, pack('B', len(fname)) + fname.encode())
while True:
data2 = f.read(BUFSIZE)
if not data2:
break
send(sock2, data2)
sock2.close()
When host2 receives this string, it will convert it to list again, but I receive an EOFError in this part. My cmd doesn't have the copy capability, so I upload the photo from this error:
What's wrong?
you delete the pointer to what is being pickled
transferStart = start[-num:]
del start[-num:]
l.release()
msg = pickle.dumps(transferStart)
If you are trying to remove elements from a list that is not the way to do it. Consider popping or reassigning into another list that does not have that element, etc.
I'm using a multiprocess to make 2 tasks. A process 1 is a async tcp server which receives commands and have to pass these commands to process 2 (is a while true loop).
How i'm using multiprocessing, the process don't share global variables, so i have to use a queue. But, a proccess 1 is a simple asynctcp server. I don't know how to pass the queue object to handle_read fuction.
Anyone have an idea? Thanks a lot!
The code i'm trying:
#!usr/bin/env python3
#import dos módulos necessarios
import time
import collections
from datetime import datetime
from datetime import timedelta
from threading import Timer
import os
import sys
from smbus import SMBus
from struct import pack, unpack
import threading
from multiprocessing import Process, Queue
import asyncore
import socket
bstatus = 0
lastdata = {}
#bytechecksum para confirmação
chksum = 15
#funções auxiliares
def millis():
dt = datetime.now()-start_time
ms = (dt.days*24*60*60 + dt.seconds)*1000+dt.microseconds / 1000.0
return ms
def getbit(data,index):
return(data & (1<<index)!=0)
def parseData(data):
mydata = {}
if data[8] == 27:
mydata['Temp1'] = data[0]
mydata['Temp2'] = data[1]
mydata['Temp3'] = data[2]
mydata['Temp4'] = data[3]
mydata['HotFlow'] = data[4]
mydata['ColdFlow'] = data[5]
mydata['PumpSpeed'] = data[6]
mydata['PumpStatus'] = getbit(data[7],0)
mydata['HeaterStatus'] = getbit(data[7],1)
mydata['ArduinoMode'] = getbit(data[7],2)
mydata['TimeStamp'] = timezone.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
#pegar o modo do arduino
arduino_mode = mydata['ArduinoMode']
parseStatus = True
else:
parseStatus = False
return parseStatus, mydata
#classes para implmmentar o servidor assincrono
class dataHandler(asyncore.dispatcher_with_send):
#this function doesn't working
def __init__(self,sock,queue):
self.queue = queue
self.sock = sock
def handle_read(self):
data = self.sock.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
'''
if(data == b'7'):
operation_mode = 1
queue.put(data)
print(data)
elif(data == b'8'):
operation_mode = 0
queue.put(data)
print(data)
try:
bytescommand = pack('=cb',data,chksum)
bus.write_block_data(arduinoAddress,ord(data),list(bytescommand))
except Exception as err:
print(str(err))
finally:
pass
#print(data)
class Server(asyncore.dispatcher):
def __init__(self,host,port,queue):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.bind((host,port))
self.listen(1)
self.queue = queue
def handle_accept(self):
pair = self.accept()
if pair is None:
return
else:
sock,addr = pair
handler = dataHandler(sock,self.queue) #doesn't working
#classe para implementar a função principal
def tcpserver(queue):
server = Server('localhost',8080,queue)
asyncore.loop()
def mainloop(stime,ftime,queue):
prevmillis = stime
prevmillis2 = ftime
operation_mode = 1
while True:
try:
currentmillis2 = millis()
if(queue.empty):
pass
else:
print(queue.get())
if(currentmillis2 - prevmillis2 > readinterval):
#do some stuff
#programa principal
if __name__=='__main__':
prevmillis= millis() #contador para solicitação de dados para o arduino
prevmillis2 = prevmillis #contador para envio do banco
#create Queue
queue = Queue()
p1 = Process(target=tcpserver,args=(queue,))
p1.start()
p2 = Process(target=mainloop,args=(prevmillis,prevmillis2,queue,))
p2.start()
strstatus = 'Servidor rodando'
print(strstatus)
In mainloop you don't test the return value of queue.empty, you test the function object itself. That always evaluates True, so it looks like queue is always empty. Change to a function call:
def mainloop(stime,ftime,queue):
prevmillis = stime
prevmillis2 = ftime
operation_mode = 1
while True:
try:
currentmillis2 = millis()
if(queue.empty()): # Added ()
pass
else:
print(queue.get())
if(currentmillis2 - prevmillis2 > readinterval):
#do some stuff
iv created a simple async client and server but im unable to get the client to reply after receiving the first time. It seems the server can send back a reply after receiving from the client but the client cant:
here is the client's session:
[mike#mike Public]$ python cl.py
buf got your stuff
dded callback ## this is a log addded to see if execution got where i wanted
and here is the server's log:
[mike#mike Public]$ python that.py
buf ehlo localhost
i was expecting some sort of ping pong effect where one send then the other then rinse lather repeat.
here is the client's code:
import socket
import fcntl, os, io, time, functools
from tornado import ioloop
class Punk(object):
def __init__(self):
self.loop = ioloop.IOLoop.instance()
self.address = 'blah.sock'
self.authkey = "none"
self.sock = socket.socket(socket.AF_UNIX)
def setup(self):
self.sock.connect(self.address)
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
self.sock.sendall("ehlo localhost")
self.fd = self.sock.fileno()
self.loop.add_handler(self.fd,self.reader,self.loop.READ)
self.loop.start()
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
try:
while True:
servrep = self.sock.recv(1024)
if not servrep:
break
result += servrep
self.prnt(result)
break
except Exception as e:
print "this %s happend"%e
return
def prnt(self,buf):
print "buf %s"%buf
tim = time.time() + 2
self.loop.instance().add_timeout(tim, self.reply)
#callbac = functools.partial(self.loop.add_timeout,tim,self.reply)
#self.loop.add_callback(self.reply) ### i tried this too
print "added callback"
def reply(self):
self.sock.sendall(" clent got your stuff")
if __name__ == "__main__":
bob = Punk()
bob.setup()
and here is the server:
import socket
import fcntl, os, io, time, functools
from array import array
from tornado import ioloop
class Player(object):
def __init__(self):
self.loop = ioloop.IOLoop.instance()
self.address = 'blah.sock'
self.authkey = "none"
self.sock = socket.socket(socket.AF_UNIX)
def setup(self):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
self.sock.bind(self.address)
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
self.sock.listen(1)
self.fd = self.sock.fileno()
self.loop.add_handler(self.fd,self.reader,self.loop.READ)
self.loop.start()
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
self.conn, self.addr = self.sock.accept()
try:
while True:
maxrep = self.conn.recv(1024)
if not maxrep:
break
result += maxrep
self.prnt(result)
break
except Exception as e:
print "this %s happend"%e
return
def prnt(self,buf):
print "buf %s"%buf
tim = time.time() + 2
self.loop.instance().add_timeout(tim, self.reply)
#callbac = functools.partial(self.loop.add_timeout,tim,self.reply)
#self.loop.add_callback(callbac)
def reply(self):
self.conn.sendall("got your stuff")
if __name__ == "__main__":
bob = Player()
bob.setup()
i had set my sockets to nonblock mode, but i did not catch an error when accepting from
a nonblock state when there is no connection:
here:
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
self.conn, self.addr = self.sock.accept()
should be
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
try:
self.conn, self.addr = self.sock.accept() # we get stuck here
self.connl.append(self.conn)
except Exception as e:
pass