Currently, I have a simple websocket server that can handle recv and send operations. The code is as such.
async def recv_handler(websocket):
while True:
try:
message = await websocket.recv()
print(message)
except Exception as e:
print(e)
await asyncio.sleep(0.01)
async def send_handler(websocket):
while True:
try:
data = {
"type&qu开发者_运维百科ot;: "send",
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
await websocket.send(json.dumps(data))
except Exception as e:
print(e)
await asyncio.sleep(0.01)
async def main(websocket):
while True:
recv_task = asyncio.create_task(recv_handler(websocket))
send_task = asyncio.create_task(send_handler(websocket))
await asyncio.gather(recv_task, send_task)
async def start_server():
server = await websockets.serve(main, "", 3001)
await server.wait_closed()
if __name__ == "__main__":
asyncio.run(start_server())
This successfully runs a server, hand can handle message sent from a client node.js application using websockets as well as send updates to the client node.js application periodically.
// receive a message from the server
socket.addEventListener("message", ({ data }) => {
const packet = JSON.parse(data);
switch (packet.type) {
case "send":
console.log(packet.time)
break;
default:
break;
}
});
// send message to server
const onClickSend = () => {
if (socket.readyState !== WebSocket.OPEN) {
console.log("socket not open");
return;
} else {
socket.send(JSON.stringify({
type: "hello from client",
}));
}
}
Now, I want to include a blocking function call that sends a pycurl (or any http) request, then use the result of that pycurl request, package it into the json object, and send that to the client.
I have a sample pycurl requst that gets the weather from wttr.in
def getWeather():
# Creating a buffer as the cURL is not allocating a buffer for the network response
buffer = BytesIO()
c = pycurl.Curl()
#initializing the request URL
c.setopt(c.URL, 'wttr.in/Beijing?format="%l:+\%c+%t+%T\\n"')
#setting options for cURL transfer
c.setopt(c.WRITEDATA, buffer)
#setting the file name holding the certificates
c.setopt(c.CAINFO, certifi.where())
# perform file transfer
c.perform()
#Ending the session and freeing the resources
c.close()
#retrieve the content BytesIO
body = buffer.getvalue()
#decoding the buffer
return body.decode('utf-8')
So if we change data to include or weather,
date = {
"type" : "send",
"weather" : getWeather(),
}
and we can slightly change the node.js application case statement to print
case "send":
console.log(packet.weather)
The problem with this, I believe, is that we are making a blocking request, but I don't know enough on how to fix the problem. Currently, I can make requests, but every time the "onClickSend" is called (by pressing a button in frontend", now, we get an error saying that the "socket not open", meaning the backend is no longer handling receive messages.
So how do I handle pycurl requests in asyncio-websocket program?
精彩评论