首页 > 解决方案 > 我在 Flutter 中的应用集成了与 Socket.io 的聊天,并且不连接到远程服务器

问题描述

开发一个包含使用 Socket.io 的聊天的 Flutter 应用程序

该服务器由 AWS 上的 EC2 实例托管。我首先在本地计算机上进行了测试。

使用 socket.io 和 Web 客户端创建一个服务器来测试连接,它工作正常。

服务器代码:

const path = require("path");
const http = require('http');
const express = require("express");
const socketio = require("socket.io");
const app = express();



app.set('port', 3000);

//static files

app.use(express.static(path.join(__dirname, "public")));

//start the server
const server = app.listen(app.get('port'), () => {

    console.log("server on port", app.get('port'));

});

const server2 = http.createServer(server);

const io = socketio(server);

//websockects

io.on('connection', (socket) => {


    console.log("new connection  " + socket.id);
    console.log(socket);


    socket.on('chat:message', (data) => {
        console.log(data.constructor.name);
        console.log(data);


        io.sockets.emit("chat:server", data);

    });

    socket.on('chat:typing', (data) => {
        console.log(data);

        socket.broadcast.emit("chat:typing", data);

    });

    socket.on('message', (data) => {
        console.log(data.constructor.name);
        console.log(data);


        io.sockets.emit("news", { respuesta: "Recibio" });

    });
});

客户端代码:

///coneccion al servidor
const socket = io();

//dom elements
let message = document.getElementById("message");
let username = document.getElementById("username");
let btn = document.getElementById("button");
let output = document.getElementById("output");
let actions = document.getElementById("actions");

//evento de envio de mensaje
btn.addEventListener('click', function() {
    console.log({
        username: username.value,
        message: message.value
    });
    //socket que emite el mensaje al servidor
    socket.emit("chat:message", {
        username: username.value,
        message: message.value
    });
});


//Escuchador de teclado, se activa cuando el usuario teclea
message.addEventListener('keypress', function() {
    //emite  el nombre del usuario cuando este esta teclando al lado del cliente
    socket.emit("chat:typing", username.value);
    socket.emit("message", username.value);
});

//socket que recibe los mensajes del servidor
socket.on("chat:server", function(data) {
    console.log(data);
    actions.innerHTML = "";
    output.innerHTML += "<p><strong>" + data.username + "</strong>: " + data.message + " </p>";

});

//socket que recibe el nombre del usuario que esta teclando
socket.on("chat:typing", function(data) {
    console.log(data);
    actions.innerHTML = "<p><strong>" + data + "</strong> esta escribiendo </p>";

});

socket.on("news", function(data) {
    console.log(data);

});

之后,我将服务器代码上传到 EC2 实例。服务器使用 NGINX,我必须对其进行修改,以便它接受来自服务器外部的连接,如下所示:

Access-Control-Allow-Origin: *

我只是修改了客户端的连接套接字:

const socket = io("https://mycustomdomain.org");

并且工作,从我的电脑连接到服务器。现在我的问题是颤振。我尝试了两个库:

-https://pub.dev/packages/socket_io_client -https://pub.dev/packages/adhara_socket_io

使用这两个库中的任何一个,我都无法连接到服务器。在 localhost 中它可以工作,但是当我尝试连接到 EC2 服务器时,我无法连接。

我做了每个库的简单例子,

与阿达拉:

Future<void> socketConfig() async {
        SocketIOManager manager = SocketIOManager();
        SocketIO socket = await manager.createInstance('https://mycustomdomain.org');       //TODO change the port  accordingly
        socket.onConnect((data){
          print("connected...");
          print(data);
          socket.emit("message", ["Hello world!"]);
        });
        socket.on("news", (data){   //sample event
          print("news");
          print(data);
        });
        socket.connect();
        ///disconnect using
        ///manager.
    }

    socketConfig();

并使用 socket.io-client

import 'package:socket_io/socket_io.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

main() {
    // Dart server
    var io = new Server();
    var nsp = io.of('/some');
    nsp.on('connection', (Socket client) {
      print('connection /some');
      client.on('msg', (data) {
        print('data from /some => $data');
        client.emit('fromServer', "ok 2");
      });
    });
      io.on('connection', (Socket client) {
        print('connection default namespace');
        client.on('msg', (data) {
          print('data from default => $data');
          client.emit('fromServer', "ok");
        });
      });
      io.listen(3000);

    // Dart client
    IO.Socket socket = IO.io('https://mycustomdomain.org/');
    socket.onConnect((_) {
     print('connect');
     socket.emit('msg', 'test');
    });
    socket.on('event', (data) => print(data));
    socket.onDisconnect((_) => print('disconnect'));
    socket.on('fromServer', (_) => print(_));
}

它甚至无法检测到它们连接到服务器。顺便说一句,我的域有 SSL 证书。

知道会发生什么吗?

标签: flutteramazon-ec2socket.io

解决方案


我的node.js项目使用的是socket.io 3.0.0版(最新的),但是我的flutter客户端好像不支持,所以尝试降级到2.3.0版(不要手动做,在换句话说不要手动修改文件)

npm uninstall socket.io
npm install socket.io@2.3.0

由于某种原因,“自动连接”不起作用,因此请尝试手动连接。

IO.Socket socket = IO.io('https://mycustomdomain.org', <String, dynamic>{
    'transports': ['websocket'],
    'autoConnect': false,
});
    
// Dart client
socket.on('connect', (_) {
    print('connect');
});
socket.on('event', (data) => print(data));
socket.on('disconnect', (_) => print('disconnect'));
socket.on('fromServer', (_) => print(_));

// add this line
socket.connect();

推荐阅读