So, I Have django app with traffic.py to send data to client (traffic.html)
class ClientTraffic(WebsocketConsumer):
def connect(self):
self.accept()
# LOOP here for send traffic when current url is x
output = item.generateTraffic()
u = float(output['tx-bits-per-second'])/1000000,
d = float(output['rx-bits-per-second'])/1000000,
self.send(json.dumps({
'upload': '{:.2f}'.format(u[0]),
'download': '{:.2f}'.format(d[0]),
}))
sleep(1)
My Question is, how I can loop send message to client while the client is in that current url (ex: /traffic/), so when client is change current page (close or go to another path) the websocket connection is close.
Related
I'm trying to make a program that reads in data as well as sends and receives data from a server through a websocket. The goal is to create synchronized lamps where there are two client lamps and one server. When one of the lamps changes state it sends a request to the server and the server updates the other lamp. I'm currently stuck on the client code. I can establish a websocket connection to the server, read and send data to the server, and I can read in light data. I'm having an issue running both of these tasks simultaneously. I'd like to do it asynchronously to avoid race condition issues. I'm using python 3.8 and asyncio.
Here is my websocket client code so far:
async def init_connection(message):
global CONNECTION_OPEN
global CLIENT_WS
uri = WS_URI
async with websockets.connect(uri) as websocket:
CONNECTION_OPEN = True
CLIENT_WS = websocket
# send init message
await websocket.send(message)
while CONNECTION_OPEN:
await handleMessages(websocket, message)
await websocket.send(json.dumps({'type': MessageType.Close.name, 'message': USERNAME}))
await websocket.close()
Here is my read in data code so far:
async def calculate_idle(t):
global STATE
global prevColor
x_arr = []
y_arr = []
z_arr = []
while t >= 0:
x, y, z = lis3dh.acceleration
print("Current colors")
print(accel_to_color(x,y,z))
x_arr.append(x)
y_arr.append(y)
z_arr.append(z)
newColor = accel_to_color(x,y,z)
# remember prev color
do_fade(prevColor, newColor)
#strip.fill((int(a_x), int(a_y), int(a_z), 0))
#strip.show()
prevColor = newColor
time.sleep(.2)
t -= .2
is_idle = is_lamp_idle(np.std(x_arr), np.std(y_arr), np.std(z_arr))
if is_idle and STATE == "NOT IDLE" and CONNECTION_OPEN:
STATE = "IDLE"
print("Sending color")
await asyncio.sleep(1)
elif is_idle and CONNECTION_OPEN:
# Check for data
STATE = "IDLE"
print ("Receiving data")
await asyncio.sleep(1)
elif is_idle and not CONNECTION_OPEN:
print ("Idle and not connected")
rainbow_cycle(0.001) # rainbow cycle with 1ms delay per step
await asyncio.sleep(1)
else:
STATE = "NOT IDLE"
await asyncio.sleep(1)
print("Is not idle")
Here is the code that is supposed to tie them together:
async def main():
message = json.dumps({'type': "authentication", 'payload': {
'username': 'user1', 'secret': SHARED_SECRET}})
loop = asyncio.get_event_loop()
start_light = asyncio.create_task(calculate_idle(3))
await asyncio.gather(init_connection(message), start_light)
asyncio.run(main())
There's other functions, but the premise is there's a websocket connection sending and receiving data and another process reading in light data. I also need to be able to read the current state of the lights and set the current state of the lights which is why I was using global variables. Currently, it'll read the lights until it hits an await asyncio.sleep(1) in calculate idle, then switch to the websocket code and hang receiving data from the server. Ideally, it would alternate between reading the current state and checking for websocket messages. If the state changes, it would then send a websocket message.
How can I run both of these routine asynchronously and share the data between them? Any help is appreciated!
Thanks to user4815162342's comments to help narrow down the issue. My calculate idle didn't have a while true and I changed time.sleep(.2) to await asyncio.sleep(.2) and I was able to read data from the server and the lights at the same time.
I am trying to write a simple chat server, that takes message from 1 user and sends to all other users. The other users can simultaneously send messages and receive them.
On client side one thread continuously waits for messages and other thread sends messages.
import socket
import threading
def getMessage(s):
while True:
s.send(raw_input("Message: "))
#Main
port = 1041
host = 'localhost'
s = socket.socket()
s.connect((host, port))
background_thread = threading.Thread(target=getMessage, args=(s,))
background_thread.daemon = True
background_thread.start()
while True:
print s.recv(1024)
On server side the server, takes the incoming connection request, opens a new thread for each new request and waits for their messages, when a connection sends a message, the server broadcasts it to all other connections that are open.
import socket
from thread import *
def ClientThread(connection, clients):
while True:
message = connection.recv(1024)
connection.send("Ack\n")
broadcast(connection, clients, message)
def broadcast(connection, clients, message):
for conn in clients:
if(conn != connection):
conn.send(message)
def AcceptConnections(clients):
while True:
connection, address = s.accept()
print "Got connection from ",connection
clients.append(connection)
start_new_thread(ClientThread, (connection, clients))
#Main
print "Started server"
port = 1041
host = 'localhost'
s = socket.socket()
s.bind((host, port))
s.listen(5)
clients = []
AcceptConnections(clients)
Expected: When one client sends a message, all other connected clients receive that message, irrespective of them typing and sending a message.
Reality: Other clients receive the message only after they send 1 or 2 messages.
I'm trying to write an asyncio-based server. The problem is, that it stops to respond after the first request.
My code is built upon this template for echo-server and this method to pass parameters to coroutines.
class MsgHandler:
def __init__(self, mem):
# here (mem:dict) I store received metrics
self.mem = mem
async def handle(self, reader, writer):
#this coroutine handles requests
data = await reader.read(1024)
print('request:', data.decode('utf-8'))
# read_msg returns an answer based on the request received
# My server closes connection on every second request
# For the first one, everything works as intended,
# so I don't thik the problem is in read_msg()
response = read_msg(data.decode('utf-8'), self.mem)
print('response:', response)
writer.write(response.encode('utf-8'))
await writer.drain()
writer.close()
def run_server(host, port):
mem = {}
msg_handler = MsgHandler(mem)
loop = asyncio.get_event_loop()
coro = asyncio.start_server(msg_handler.handle, host, port, loop=loop)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
On the client-side I either get an empty response or ConnectionResetError (104, 'Connection reset by peer').
You are closing the writer with writer.close() in the handler, which closes the socket.
From the 3.9 docs on StreamWriter:
Also, if you don't close the stream writer, then you would still have store it somewhere in order to keep receiving messages over that same connection.
import socket
host = 'address' # as you know this isn't letters but I just write it as address for now.
port = 50000
bufsize = 1024
server = socket.socket()
server.bind((host, port))
server.listen(5)
while 1:
print("Waiting Connection")
client, address = server.accept()
print("Connected")
welcomemsg = ("send messages")
client.send(bytes(welcomemsg, "utf-8"))
print("client info")
print(address)
msgfromclient = server.recv(bufsize).decode("utf8")
client.send(bytes(msgfromclient, "utf-8"))
import socket
bufsize = 1024
client = socket.socket()
while 1:
client.connect(('address', 50000))
welcomemsg = client.recv(bufsize).decode("utf8")
print(welcomemsg)
msgtoserver = input()
server.send(bytes(msgtoserver, "utf-8"))
msgfromserver = client.recv(bufsize).decode("utf8")
print(msgfromserver)
I think I can connect server and client and then I can make server send a welcome message to client and client can receive that message.
But after that I think I can't retain connection between server and client any longer.
I want to make server and client retain connection after server send a welcome message to client and client send a message to server and then server send it again to all the clients (yes I am trying to make chat program.)
I am using Windows.
I'm trying to build a simple chat app using a NodeJS server with socket.IO and a client written in python 2.7 using socketIO-client package.
The js server is on local and is very simple :
io.on('connection', function(socket){
socket.on("chat_message", function(msg){
io.emit("chat_message", msg);
});
});
This chat app works for several pages opened in my browser.
(source comes from : http://socket.io/get-started/chat/ )
I wanted to connect this server from a python client, and I succesfully emit from python to js server (text entered in python client appears into the browser).
The problem is the following :
When I type some text into the browser, Python doesn't print it into the shell.
Here is the code I use on python side :
def communicate(self, msg):
logging.debug('processing event : %s', msg)
self.socketIO.emit("chat_message", msg, self.on_chat_message)
def on_chat_message(self, *args):
output = ''
index = 0
for a in args:
output += ' | '+str(index)+' : '+str(a)
index += 1
logging.debug('processing server output : ' + output)
return
As the server emits to all connected clients, python should normally handle it into the callback 'on_chat_message' but, it doesn't work.
I also tried to add a self.socketIO.wait_for_callbacks() to the python, without success.
If someone has an idea about what I'm doing it wrong, it would be great =D !
Thanks.
I finally managed to get a response from the server on my python client.
My mistake was to not 'wait' on the socketIO variable, so I didn't catch any feedback.
To properly handle server responses, I use a BaseNamespace class which is binded to the socket, and handle basic events : overriding of the function on_event
def on_event(self, event, *args):
#Catch your event and do stuff
If an event is handled by the class, a flag is raised up and checked by the client.
def communicate(self, msg):
self.socketIO.emit('chat_message', msg)
def wait_for_server_output(self):
while(1):
self.socketIO.wait(seconds=1)
ns = self.socketIO.get_namespace()
if ns.flag.isSet():
data = ns.data_queue.get()
ns.flag.clear()
These two functions are managed by 2 threads inside the client code.
Hoping this will help =)