【问题标题】:How to use html5 websockets within sharedworkers如何在 sharedworkers 中使用 html5 websockets
【发布时间】:2021-06-22 09:43:30
【问题描述】:

在查看 stackoverflow 上的类似问题后,我没有发现任何对我想要在我的项目中做的事情有多大帮助。阅读和研究我成功地使应用程序与我的 Ratchet PHP websocket 服务器建立了多个连接,但我注意到每次用户重新加载页面或在新选项卡中打开链接时,客户端 websocket 都会断开连接,然后再次重新连接。

所以,我想知道如何在使用 Sharedworker 的 Web 应用程序中为多个用户只获得一个到 WebSocket 服务器的持久连接。

我在客户端是这样的:

<script>
$(document).ready(function($) {
   let socket = new WebSocket("ws://realtime:8090");

   socket.onopen = function(e) {
      console.log("Browser client connected to websocket server");
      socket.send("Greetings from the browser!");
   };

   socket.onmessage = function(event) {
      console.log('Data received from server: ' + event.data);
   };

   socket.onclose = function(event) {
      if (event.wasClean) {
         console.log(`Connection closed cleanly, code=${event.code} reason=${event.reason}`);
      }
      else {
         // e.g. server process killed or network down
         // event.code is usually 1006 in this case
         console.log('Connection closed unexpectedly.');
      }
   };

   socket.onerror = function(error) {
      alert(error.message);
   };     
});
</script>

【问题讨论】:

    标签: javascript html websocket


    【解决方案1】:

    好的,在阅读、研究和尝试不同的东西和代码示例之后,我得出了这个解决方案:

    客户端(浏览器)应该与 Sharedworker 建立连接。 sharedworker 是一个单独的 javascript 文件,其中包含 sharedworker 的核心以及需要在其中执行的任何其他 JS 代码。 我首先测试了 sharedworker 在浏览器选项卡上的正常工作,计算每个用户打开的选项卡的数量,并将消息共享给一个用户,然后共享给一组用户。 一旦浏览器和 Sharedworker 之间的通信通过了这些测试,我就将 websocket 代码添加到 Sharedworker JS 文件的正文中。

    最后,客户端(浏览器)是这样的:

      <script>
       $(document).ready(function($) {
          var currentUser = "{{ Auth::user()->name }}";
    
          let worker = new SharedWorker('worker.js');
          worker.port.start();
          worker.port.postMessage({
             action: 'connect',
             username: currentUser
          });
    
          worker.port.onmessage = function(message) {
             console.log(message.data);
          };
    
       });
      </script>
    

    Sharedworker 如下所示:

    // All this code is executed only once, until the onconnect() function.
    //---------------------------------------------------------------------
    
    // The array AllPorts contains objects with the format {user:<string>, port:<MessagePort>}
    let AllPorts = [];
    
    var socket = new WebSocket("ws://ssa:8090");
    
    // Called when the WebSocket Server accepts the connection.
    socket.onopen = function(e) {
       //
    };
    
    // Event handler fired when the WebSocket Server sends a message to this client.
    socket.onmessage = function(e) {
       var message = JSON.parse(e.data);
       // This loop sends a message to each tab opened by the given user.
       for (var i = 0; i < AllPorts.length; i++) {
          if (AllPorts[i].user == message.to) {
             AllPorts[i].port.postMessage(message.msg);
          }
       }
    };
    
    socket.onclose = function(event) {
       if (event.wasClean) {
          console.log('Connection closed normally');
       }
       else {
          console.log('Connection closed unexpectedly.');
       }
    };
    
    socket.onerror = function(error) {
       console.log(error.message);
    };
    
    
    
    // This event handler is fired every time a new tab is opened on the web browser.
    onconnect = function(ev) {
       let port = ev.ports[0];
    
       port.onmessage = function(e) {
          console.log(e.data.action);
          let currentUser = e.data.username;
          let userIsConnected = false;
    
          switch (e.data.action) {
             case "connect":
                for (var i = 0; i < AllPorts.length; i++) {
                   if (AllPorts[i].user == currentUser) {
                      userIsConnected = true;
                   }
                }
                // Add new connected tab to AllPorts array.
                AllPorts.push({user: currentUser, port: port});
                if (!userIsConnected) {
                   // New users are added to the list of the WebSocket Server.
                   setTimeout(() => {
                      socket.send(JSON.stringify({action: 'connect', username: currentUser}));
                   }, 600);
                }
                break;
    
             case "close":
                console.log(AllPorts);
                var index;
                // This is also executed when the user reloads the Tab.
                for (var i = 0; i < AllPorts.length; i++) {
                   if (AllPorts[i].port == port) {
                      index = i;
                      currentUser = AllPorts[i].user;
                   }
                }
                AllPorts.splice(index, 1);
                userIsConnected = false;
                // Check for any connected tab.
                for (var i = 0; i < AllPorts.length; i++) {
                   if (AllPorts[i].user == currentUser) {
                      userIsConnected = true;
                   }
                }
                if (!userIsConnected) {
                   // User doen't have more tabs opened. Remove user from WebSocket Server.
                   socket.send(JSON.stringify({action: 'disconnect', username: currentUser}));
                }
                break;
    
             case "notify":
                // Check if given user is connected.
                for (var i = 0; i < AllPorts.length; i++) {
                   if (AllPorts[i].user == currentUser) {
                      userIsConnected = true;
                   }
                }
                if (userIsConnected) {
                   socket.send(JSON.stringify({action: 'notify', to: currentUser, message: e.data.message}));
                }
          } // switch
       } // port.onmessage
    } // onconnect
    

    【讨论】:

      猜你喜欢
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多