首页 > 解决方案 > 将 Flask-SocketIO 与 Node socket.io-client 或 ngx-socket-io 连接时出现问题

问题描述

目前我正在使用 Ionic 和 Flask_SocketIO 开发一个实时聊天应用程序

我确实需要 Flask 作为后端,因为我正在使用 Flask_login 处理身份验证。问题似乎出在我的应用程序的 nodejs-angular-ionic 方面。应用程序可以正确连接和验证,但是一旦我从 IonicClient 向其他客户端(例如来自网络)发出消息,它们似乎停止接收,但我仍然能够从这些客户端发出消息。服务器实际上确实将它们列为已连接。所以可能存在请求冲突。

如果我只使用来自网络的客户端,我的聊天会完美运行,这让我相信它与我们的 nodejs-angular-ionic-app 有关

FlaskBackend、WebClients 和 IonicClients 都不会显示错误消息。

FLASK_BACKEND

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import emit, join_room, leave_room, SocketIO, send, disconnect
import functools
from flask_login import current_user, LoginManager
from flask import g
from datetime import datetime
from itsdangerous import URLSafeTimedSerializer
from flask_socketio import ConnectionRefusedError

app = Flask(__name__)
app.config.from_pyfile('config.cfg')

socketio = SocketIO(app, manage_session=False, cors_allowed_origins='*') #http://127.0.0.1:5000
login = LoginManager(app)
db = SQLAlchemy(app)

room = None

def confirm_token(token, expiration=86400):
    serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
    try:
        id = serializer.loads(
            token,
            salt=app.config['SECURITY_PASSWORD_SALT'],
            max_age=expiration
        )
    except:
        return False
    return id


from models import UserModel, MessageModel

@login.request_loader
def load_user_from_request(request):
    # first, try to login using the api_key url arg
    id = request.args.get('id')
    if id:
        id = confirm_token(id)
        if id:
            g.login_via_header = True
            user = UserModel.query.filter_by(id=id).first()
            db.session.close_all()
            if user:
                return user
        else:
            return None
    else:
        print("No id found")
        return None

def authenticated_only(f):
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        if not current_user.is_authenticated or current_user.is_anonymous:
            print("current_user is anonymous")
            disconnect()
        else:
            return f(*args, **kwargs)
    return wrapped



@socketio.on('joined')
@authenticated_only
def joined(message):
    """Sent by clients when they enter a room.
    A status message is broadcast to all people in the room."""
    global room
    room = message['room']
    join_room(room)
    emit('status', {'msg': str(current_user.first) + ' is now Online.'}, room=room, skip_sid=True)
    print(current_user.first, "joined room no.", room)


@socketio.on('text')
@authenticated_only
def text(message):
    """Sent by a client when the user entered a new message.
    The message is sent to all people in the room."""
    global room
    msg = MessageModel(
        owner = current_user,
        room = room,
        message = str(message['msg']),
        timestamp = datetime.utcnow()
    )
    try:
        msg.save_to_db()
        emit('message', {'msg': message['msg'],
            'u_id': current_user.id,
            'u_pp': current_user.profile_picture,
            'u_name': current_user.first }, room=room, skip_sid=True)
        print(current_user.first + ": " + str(message['msg']))
    except Exception as e:
        print(e)
        raise

@socketio.on('disconnect')
def test_disconnect():
    print("Bye", current_user.first)
    global room
    leave_room(room)
    emit('status', {'msg': str(current_user.first) + ' is now Offline.'}, room=room, skip_sid=True)




if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=3001)

离子

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Socket } from 'ngx-socket-io';

const SOCKET_URL = 'http://192.168.0.125:3001?id='

@Component({
  selector: 'app-job-detail',
  templateUrl: './job-detail.page.html',
  styleUrls: ['./job-detail.page.scss'],
})


export class JobDetailPage implements OnInit {
  private id: string;
  private token: string = "MQ.XoxlTg.Pjd8WcW_e2ywu5YeabBwToz53nM";

  messages = [];

  constructor(
    private route: ActivatedRoute,
    private socket: Socket,
  ) {
  }

  ngOnInit() {
    this.id = this.route.snapshot.paramMap.get('id');

    this.socket.ioSocket.io.opts.query = {cookie: false, transports: ['websocket']};
    this.socket.ioSocket.io.uri = SOCKET_URL + this.token; //new uri
    this.socket.connect(); //manually connection

    this.socket.fromEvent('connect').subscribe( () => {
      this.socket.emit('joined', {room: this.id});
    });

    this.socket.fromEvent('disconnect').subscribe(() => {
      console.log("You disconnected from our chat servers")
    })



    //this.socket.fromEvent('status').subscribe(data => {
    //  console.log(data)
    //});
  }


  sendMessage(msg) {
    this.socket.emit('text', {
      msg: msg
    });
  }

网页

socket = io("http://192.168.0.125:3001?id={{chattoken}}", { transports: ['websocket'] });
            socket.on('connect', function() {
                socket.emit('joined', {room: room_id});
            });
            socket.on('disconnect', function() {
                console.log("You disconnected from our Chat servers")
            });
            socket.on('status', function(data) {
                console.log("Received A StatusUpdate")
                $('#chat').html($('#chat').html() + '<div style="text-align: center">' + data.msg + '</div><br>');
                $('#chat').scrollTop($('#chat')[0].scrollHeight);
            });
            socket.on('message', function(data) {
                console.log("Received A Message")
                if (data.u_id == user_id) {
                    $('#chat').html($('#chat').html() + outgoing_msg + data.msg + outgoing_msg_end);
                } else {
                    var d = new Date();
                    var h = addZero(d.getHours());
                    var m = addZero(d.getMinutes());
                    if (data.u_pp == "missing") {
                        $('#chat').html($('#chat').html() + incoming_msg + "<div class=\"incoming_msg_img\"> <img src=\"{{ url_for('static', filename='images/missing.png') }}\"> </div>" + incoming_msg_middle + data.msg + incoming_msg_end + data.u_name +
                            " today, " + h + ":" + m + incoming_msg_end_1);
                    } else {
                        $('#chat').html($('#chat').html() + incoming_msg + "<div class=\"incoming_msg_img\" style=\"background-image: url('" + data.u_pp + "'); background-size:cover; border-radius: 4rem;\"> </div>" + incoming_msg_middle + data.msg +
                            incoming_msg_end + data.u_name + " today, " + h + ":" + m + incoming_msg_end_1);
                    }
                }

                $('#chat').scrollTop($('#chat')[0].scrollHeight);
            });

经过进一步调查,我发现了这些问题: https ://github.com/miguelgrinberg/python-socketio/issues/47 https://github.com/miguelgrinberg/Flask-SocketIO/issues/253#issuecomment-233241257

但由于我也尝试了 ngx-socket-io 和 2016 年的问题,我认为它们不相关。

提前致谢,

氟草酮

标签: pythonangularionic-frameworkflasksocket.io

解决方案


推荐阅读