Closed chenzx closed 5 years ago
I'm writing a demo to streamming GLES2 cmd data to browser js via websocket and i'm following the docs.
There are 2 problems:
wait, problem 2 is solved, i found i had started 2 server scripts, and the later one didn't get any data -- that's ok, but problem 1 is still wierd...
when i access http://127.0.0.1:8888/
How are you doing this. Can you show me client code?
There are 2 clients:
1、python socketio client, to send data, this is now connected, and send OK, 2、native js client in Chrome M75:
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// 这里初始化ws连接:
var websocket = new WebSocket("ws://127.0.0.1:8888/gles2_cmd");
websocket.onmessage = function (event) {
console.log(event.data);
}
This fails, 404. I do not understand how Flask-SocketIO coordinates with Flask?
Python socketio client script:
import os, sys, socketserver, logging
import socketio
from gles2_cmd_names_gen import GLES2_cmd_packet_type_names
LOCAL_TCP_LISTEN_PORT = 9999
UPSTREAM_WEBSOCKET_SERVER = 'http://127.0.0.1:8888/gles2_cmd_input' # ?
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(levelname)s]%(message)s')
console.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.addHandler(console)
logger.setLevel(logging.DEBUG) # Fk. this line call is needed!
sio = socketio.Client()
sio.connect(UPSTREAM_WEBSOCKET_SERVER)
print('websocket client sid is', sio.sid)
class MyTCPHandler(socketserver.StreamRequestHandler):
def read_uint32(self):
data = self.rfile.read(4)
return data, int.from_bytes(data, byteorder='little', signed=False)
def handle(self):
logger.debug("enter handle ...")
while True:
l, packet_length = self.read_uint32() # 读取1个uint32_t
t, packet_type = self.read_uint32()
logger.debug("packet_length={} packet_type={}({})".format(
packet_length,
GLES2_cmd_packet_type_names[packet_type],
packet_type
)
)
packet_data_left = self.rfile.read(packet_length - 8)
total_packet_data = l + t + packet_data_left
# now send as ws client:
sio.emit("gles2_cmd_input", total_packet_data, namespace='/gles2_cmd_input')
if __name__ == "__main__":
logger.debug("starting tcp2websocket server at {} ...".format(LOCAL_TCP_LISTEN_PORT))
server = socketserver.ThreadingTCPServer(("", LOCAL_TCP_LISTEN_PORT), MyTCPHandler) # 线程
server.serve_forever()
This side is sending ok, and log hit in handle_message.
What i'm doing is: receive binary data in one "/gles2_cmd_input" namespace, and cache it in a memory queue, then broadcast to all browser clients in another namespace.
You are using a websocket client for JS. Use the Socket.IO client. They're not the same thing.
I see, i'll try...
I'm using Socket.IO client lib now:
/*
var websocket = new WebSocket("ws://127.0.0.1:8888/gles2_cmd_input");
websocket.onmessage = function (event) {
console.log(event.data);
}*/
const socket = io('/gles2_cmd');
socket.onmessage = function (event) {
console.log(event.data);
}
socket.on("gles2_cmd", function (event) {
console.log(event.data);
})
socket.connect();
But still can not receive message/data from server side. Why?
@chenzx Why don't you start from the example in this repository and adapt it to your needs?
@miguelgrinberg i made another mistake, i use a separate local port to server static index.html, and now it emits and receives ok!
Now there is only one problem left:
I have config'ed Flash static index.html to route '/', but why can't i load it using http://127.0.0.1:8888/ ?
does Flask-SocketIO call socketio.run(app, host="0.0.0.0", port=8888, debug=True)
also start Flask app?
@chenzx Yes. As I said above, please start from the example in this repository, which serves static files as well as Socket.IO.
Edit: after looking briefly at your application, my guess is that the unusual way you are handling static files is the source of your problems. I suggest you let Flask handle static files as usual.
I'm using the following simple code:
@socketio.on('gles2_cmd_input', namespace='/gles2_cmd_input')
def handle_message(gles2_cmd):
cmd_len = int.from_bytes(gles2_cmd[0:4], byteorder='little', signed=False)
cmd_type = int.from_bytes(gles2_cmd[4:8], byteorder='little', signed=False)
print('received gles2_cmd input: cmd_len={} cmd_type={}'.format(cmd_len, cmd_type))
socketio.emit('gles2_cmd', gles2_cmd, namespace='/gles2_cmd', broadcast=True)
#global gles2_cmds
#gles2_cmds.append(gles2_cmd)
if __name__ == '__main__':
# thread = socketio.start_background_task(background_thread)
socketio.run(app, host="0.0.0.0", port=8888, debug=True)
Everything is ok. Note here i'm not starting a background thread, also the wierd thing is, Flask app static serve is always NOT ok, i have to using another Python http-server script (at different port) to serve static files.
Can't figure out why.
What does "let Flask handle static files as usual" mean? I thought Flask-SocketIO is a wrapper around the Flask app so it will also start flask app internally? But seems cases are not so.
What does "let Flask handle static files as usual" mean?
I mean don't do this:
app = Flask(__name__, static_url_path='')
or this:
@app.route('/static/<path:path>')
def send_static(path):
logger.debug("path={}".format(path))
return app.send_from_directory('static', path)
Or in other words, let Flask handle static files as it does by default. Once you have that working, make the changes that you need.
browser socket.io client code: (separate ws and static index.html, it's ok)
const socket = io('ws://127.0.0.1:8888/gles2_cmd');
//io("/gles2_cmd") not ok, since Flask-SocketIO server script cannot serve static index.html
socket.on("gles2_cmd", function (data) {
// data is ArrayBuffer type;
const view = new Uint32Array(data);
let packet_length = view[0]
let packet_type = view[1]
console.log(`packet_length=${packet_length} packet_type=${packet_type}`)
})
socket.connect();
@miguelgrinberg but if i don't write any Flask static route, it(Flask) default cannot do static file serve!
app = Flask(__name__) #, static_url_path='')
'''
@app.route('/static/<path:path>')
def send_static(path):
logger.debug("path={}".format(path))
return app.send_from_directory('static', path)
@app.route('/')
def index():
logger.debug("/")
return app.send_static_file('index.html')
'''
Hi, problem solved:
app.send_static_file
seems assuming 'index.html' MUST be in 'static' sub dir. But i never config this in code! I guess this is Flask's Convention-over-Config?