简体   繁体   中英

How can I send data though socket-io without the client requesting first with python and flask

My goal is for my Flask server to send the client data either every three seconds, or when a function is called. To do this I am using SocketIO. However based on some example code I am working with, it seems that I can only send data after a client requests something. I don't want the client to have to 'poll' to find if there is new data, so I want the server to push it when it is ready.

Here is what I tried so far. (some of the code is unnecessary since it is based off an example) This should use socketio to push the time to the client every few seconds.

HTML

<!DOCTYPE HTML>
<html>
<head>
    <title>Socket-Test</title>
    <script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
    <script type="text/javascript" charset="utf-8">
        $(document).ready(function() {

            namespace = '/test';
            var socket = io(namespace);

           

            socket.on('my_response', function(msg, cb) {
                $('#log').text( $('<div/>').text(msg.data).html());
                if (cb)
                    cb();
            });
            
            
            
        });
    </script>
</head>
<body style="background-color:white;">

    <h1 style="background-color:white;">Socket</h1>
    <div id="time" ></div>
</body>
</html>

Python

import threading
from flask import Flask, render_template, session, copy_current_request_context,request
from flask_socketio import SocketIO, emit, disconnect
from threading import Lock
import time

async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socket_ = SocketIO(app, async_mode=async_mode)
thread = None
thread_lock = Lock()
clients = []
def update():
    time.sleep(1)
    emit('my_response',
         {'data': time.time},
         room=clients[0])
t=threading.Thread(target=update)



@socket_.on('connect')
def handle_connect():
    print('Client connected')
    clients.append(request.sid)
    t.start()


@app.route('/')
def index():
    
    return render_template('index.html', async_mode=socket_.async_mode)


@socket_.on('my_event', namespace='/test')
def test_message(message):
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response',
         {'data': message['data'], 'count': session['receive_count']})


@socket_.on('my_broadcast_event', namespace='/test')
def test_broadcast_message(message):
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response',
         {'data': time.time},
         broadcast=True)






socket_.run(app,port=8050)

I try to run it but it gives me the error RuntimeError: Working outside of request context.

I fixed my code by following this tutorial: https://www.shanelynn.ie/asynchronous-updates-to-a-webpage-with-flask-and-socket-io/

import threading
from flask import Flask, render_template, session, copy_current_request_context,request
from flask_socketio import SocketIO, emit, disconnect
from threading import Lock
import time

async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socket_ = SocketIO(app, async_mode=async_mode)
thread = None
thread_lock = Lock()

def update():
    
    time.sleep(1)
    socket_.emit('my_response',
         {'data': time.time()},
        namespace='/test')
    print("emitted")
    update()
t=threading.Thread(target=update)



@socket_.on('connect', namespace='/test')
def handle_connect():
    print('Client connected')
   
    if not t.isAlive():
        t.start()


@app.route('/')
def index():
    
    return render_template('index.html', async_mode=socket_.async_mode)


socket_.run(app,port=8070)

HTML

<!DOCTYPE HTML>
<html>
<head>
    <title>Socket-Test</title>
    <script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
    <script type="text/javascript" charset="utf-8">
        $(document).ready(function() {

            namespace = '/test';
            var socket = io(namespace);

           console.log(("test"));

            socket.on('my_response', function(msg) {
                $('#time').text( $('<div/>').text(msg.data).html());
                
                console.log(msg);
            });
            
            
            
        });
    </script>
</head>
<body style="background-color:white;">

    <h1 style="background-color:white;">Socket</h1>
    <div id="time" ></div>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM