Soulstorm89
Soulstorm89

Reputation: 1

Client can send but not receive. (server: Flask SocketIO python) (client: socket.io.min.js)

I've got about 100 lines of code that require some expertise. I'm working on a classic client-server structure using flask and websockets. The communication from the client to the server works fine, but the communication from the server to the client doesn't work at all.

My client is pretty straightforward:

    var socket = io({
        transports: ['websocket'],
        pingInterval: 25000, // ping every 25 sec
        pingTimeout: 10000   // timeout 10 sec
    });

    socket.on('connect', function () 
    {
        console.log('Connected')
        socket.emit('pin:8989')

    });

    socket.on('update', function (data) {
        print(data)
        const json_data = JSON.parse(data);
        Object.keys(json_data).forEach(key => {
            const update = json_data[key];
            if (update.key) document.getElementById(update.key).innerHTML = update.value;});});

    function send(request) {
        if (request) {
            socket.emit('request', request);
            console.log('Sent:', request);}
        }

It should connect, receive and process JSON, and be able to send requests.

The server is a bit more juicy:

# Interface Terminal
from threading import Thread, Event
from flask import Flask, request, render_template
from flask_socketio import SocketIO
from abc import abstractmethod
from system.error_handler import err_terminal
import datacore
import time

flask = Flask('undefined') # flask webserver (HTTP)
socket = SocketIO(flask, cors_allowed_origins="*") # flask socket io (TCP)

class Terminal():
    def __init__(self, name, host, port, templates, statics):
        self.core = datacore.Cores.TERMINAL
        flask.terminal_instance = self  # store this instance in the app
        flask.name = name  # application name
        flask.template_folder = templates  # path to templates folder (index > .html)
        flask.static_folder = statics      # path to static files folder (.js .css .png ...)
        self.flask_thread = Thread(target=socket.run, args=(flask, host, port))
        self.feeding_thread = Thread(target=self.feed)
        self.stop_feeding = Event()             # event to signal stop feeding clients
        
    #run app
    def run(self):  
        try:
            self.flask_thread.start()
            self.feeding_thread.start()
        except Exception as e:
            err_terminal('Fail to run', e)

    #stop app
    def stop(self):
        try:
            self.stop_feeding.set()  # signal the feed task to stop
            self.feeding_thread.join()
            socket.stop()  # stop flask
        except Exception as e:
            err_terminal('Fail to stop', e)

    # send data
    def send(self, data, event='update'): 
        try:
            socket.emit(event, data)  # send data to all connected clients
        except Exception as e:
            err_terminal('Fail to send', e)

    # feed data (task: periodically emit to clients)
    def feed(self):
        while not self.stop_feeding.is_set():
            package = {}                # empty package
            self.on_packJSON(package)   # populate the package
            self.send(package)          # send package
            time.sleep(1)               # loop once a sec
    
    # hooks for the subclass
    @abstractmethod
    def on_packJSON(self, package): pass    # hook to packing data   
    @abstractmethod
    def on_receive(self, request): pass     # hook to incoming request (unpacking)
    @abstractmethod
    def on_connect(self, address): pass     # hook to client connection
    @abstractmethod
    def on_disconnect(self, address): pass  # hook to client disconnection

# flask handlers
@flask.route('/')           # render index.html
def index(): return render_template('index.html', title=flask.name)
@socket.on('request')       # incoming request
def receive(request): flask.terminal_instance.on_receive(request)
@socket.on('connect')       # client connection
def connect(): flask.terminal_instance.on_connect(request.remote_addr)
@socket.on('disconnect')    # client disconnection
def disconnect(): flask.terminal_instance.on_disconnect(request.remote_addr)
@socket.on('error')         # client error
def error(err): err_terminal('Client error', err)

I'm using Flask as webserver and websocket server. Class Terminal hosts two threads: the first one runs flask, while the second one runs a feeding stream to clients. Packing data to send, unpacking receiving data, and monitor clients is delegated to a sub class.

Clients can connect to the server and send data, but it didn't matter what I tried, clients won't receive anything back. I tested it extensively in a local net but nothing. If I stop sending requests from a client, it enters in a disconnect/connect loop.

>>> 05:22 192.168.158.127 connected
<<< 05:22 192.168.158.127 disconnected
>>> 05:23 192.168.158.127 connected
<<< 05:23 192.168.158.127 disconnected
>>> 05:23 192.168.158.127 connected

I'm assuming is because it's not receiving anything from the server, but I'm not even sure it is related (it behave like that even without setting a timeout). I tried to monitor the client with something like this to catch all possible events:

socket.onAny((event, ...args) => {console.log(event,args);});

But it doesn't even catch the 'connect' one. I feel the problem might lay in the way I'm dealing with events to handle incoming data, as the other channel (client to server) works perfectly, but it could also be my setup.

Ok, I'm out of bullets for this one. Any good insight or suggestion to be back on track to solve it?

[UPDATE] I wrote down a small client in python to test the server. Same results. So I tried to write another server using native websockets rather than flask and... well, you guessed right. =( So, it's not the client apparently. Something is blocking messages from my hosts. I toyed a bit with port forwarding but nothing.

Upvotes: 0

Views: 35

Answers (0)

Related Questions