0

我一直在尝试socket.io在我的 Loopback 3 应用程序中实现设备激活系统。到目前为止,我有 2 个问题socket.io。首先,由于某种原因,我遇到了连接本身的问题,它不断地连接和断开连接。所以我开始做一些研究,但我很快发现这是一个已知问题,一个可能的解决方案是将版本从 v4 更改为 v2(但这并没有解决我的问题),或者主动 ping客户。

因此,当我尝试后者时,只要仅建立 1 个连接,我就能完美地做到这一点。建立第二个连接后,一切都变得混乱。由于两个连接都被 ping 两次而不是一次,所以当我开始更多连接时,它只会 ping 更多。这意味着如果建立了 10 个连接,则每个连接都被 ping 了 10 次,这当然不应该发生。

我已经尝试了很多东西,但我现在有点没有想法了。

这是我的服务器端 server.js 代码:

// Copyright IBM Corp. 2016. All Rights Reserved.
// Node module: loopback-workspace
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

"use strict";

var loopback = require("loopback");
var boot = require("loopback-boot");

var app = (module.exports = loopback());

app.start = function () {
  // start the web server
  return app.listen(function () {
    app.emit("started");
    var baseUrl = app.get("url").replace(/\/$/, "");
    console.log("Web server listening at: %s", baseUrl);
    if (app.get("loopback-component-explorer")) {
      var explorerPath = app.get("loopback-component-explorer").mountPath;
      console.log("Browse your REST API at %s%s", baseUrl, explorerPath);
    }
  });
};

// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function (err) {
  if (err) throw err;

  // start the server if `$ node server.js`
  if (require.main === module) {
    app.io = require("socket.io")(app.start(), {
      cors: {
        origin: "*",
      },
    });
    app.io.on("connection", (socket) => {
      console.log("a connection has been established");
      socket.on("pong", function (data) {
        console.log("Pong received from client");
      });
      setTimeout(sendHeartbeat, 10000);

      function sendHeartbeat() {
        setTimeout(sendHeartbeat, 10000);
        console.log("Ping send to client");
        app.io.emit("ping", { beat: 1 });
      }
      socket.on("joinRoom", (code) => {
        socket.join(code);
      });
      socket.on("leaveRoom", (code) => {
        socket.leave(code);
      });
      socket.on("activateCode", (code, name, companyId) => {
        socket.join(code);
        socket.broadcast.to(code).emit("activate", name, companyId);
      });
      socket.on("deviceActivated", (code, err, res) => {
        socket.broadcast.to(code).emit("activated", code, err, res);
        socket.leave(code);
      });
      socket.on("activationFinished", (code) => {
        socket.leave(code);
      });
      socket.on("disconnect", () => {
        console.log("user/device disconnected");
      });
    });
  }
});

这是我的客户端 kotlin 代码(这是唯一使用套接字的地方):

package ikanda.roombookingdisplays.fragments

import SocketHandler
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import ikanda.roombookingdisplays.R
import ikanda.roombookingdisplays.base.AppNavigation
import ikanda.roombookingdisplays.model.Setting
import ikanda.roombookingdisplays.ui.SettingViewModel
import io.socket.client.Socket
import io.socket.emitter.Emitter
import kotlinx.android.synthetic.main.fragment_activation.*
import org.json.JSONException
import org.json.JSONObject


/**
 * A simple [Fragment] subclass.
 * Use the [ActivationFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class ActivationFragment : Fragment() {

    private lateinit var navigationCallback: AppNavigation
    private lateinit var deviceActivated: Setting
    private lateinit var settings: Array<Setting>
    private lateinit var viewModel: SettingViewModel
    private lateinit var currentView: View
    private lateinit var mSocket: Socket
    private var amountOfPings: Int = 0

    private var code =
        java.util.UUID.randomUUID().toString().substring(2, 5) + java.util.UUID.randomUUID()
            .toString().substring(2, 5)

    private var isActivated = false

    override fun onAttach(context: Context) {
        super.onAttach(context)
        navigationCallback = context as AppNavigation
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(requireActivity()).get(SettingViewModel::class.java)
        SocketHandler.setSocket()
        SocketHandler.establishConnection()
        mSocket = SocketHandler.getSocket()
        mSocket.on("ping", onPing)
        mSocket.on("activate", onActivate)
        mSocket.on("disconnect", onDisconnect)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // Inflate the layout for this fragment
        currentView = inflater.inflate(R.layout.fragment_activation, container, false)
        return currentView
    }

    override fun onStart() {
        super.onStart()
        codevalue.text = code
        mSocket.emit("joinRoom", code)
    }

    private val onPing = Emitter.Listener { args ->
        requireActivity().runOnUiThread(Runnable {
            val data = args[0] as JSONObject
            val ping: String = try {
                data.getString("beat")
            } catch (e: JSONException) {
                return@Runnable
            }
            if (ping == "1") {
                amountOfPings += 1
                if (amountOfPings == 20) {
                    mSocket.emit("leaveRoom", code)
                    resetCode()
                } else {
                    mSocket.emit("pong", "pong")
                }
            }
            Log.e("SOCKETPING", "RECEIVED PING! ")
        })
    }


    private val onActivate = Emitter.Listener {
        mSocket.off("activate")
        navigationCallback.activateDevice()
    }

    private val onDisconnect = Emitter.Listener {
        requireActivity().runOnUiThread(Runnable {
            resetCode()
            Log.e("socket.io", "Disconnected device")
        })
    }

    private fun resetCode() {
        code = java.util.UUID.randomUUID().toString().substring(2, 5) + java.util.UUID.randomUUID()
            .toString().substring(2, 5)
        amountOfPings = 0;
        codevalue.text = code
        mSocket.emit("joinRoom", code)
    }

    override fun onDestroy() {
        super.onDestroy()
        SocketHandler.closeConnection()
    }

    companion object {
        @JvmStatic
        fun newInstance() =
            ActivationFragment()
    }
}

关于如何解决这个问题或我做错了什么的任何想法?

4

0 回答 0