【问题标题】:WebSocket server-side script callWebSocket 服务器端脚本调用
【发布时间】:2014-06-20 21:04:09
【问题描述】:

WebSocket 教程说需要两件事:

*1。应该启动服务器端脚本:

php -q path/to/server.php

*2。客户端脚本应该打开套接字连接:

var socket = new WebSocket('ws://example.com:12345/server.php');

但是请求 'ws://example.com/server.php' 会再运行一次服务器脚本。这将导致运行多个服务器实例。或者客户端请求会导致服务器端错误(socket_bind(...) => 已经绑定)。

有人能解释一下这种沟通模式吗?谢谢。

【问题讨论】:

    标签: php sockets websocket


    【解决方案1】:

    根据我对 websocket 的理解:当您运行服务器脚本时,它会侦听来自example.com 域名、12345 端口和ws:// 协议的所有请求。

    因此,当您从客户端调用new WebSocket('ws://example.com:12345/server.php'); 时,它会向正在运行的server.php 发送请求。无论如何,它不会导致服务器再次运行。

    我不知道细节,但是当我尝试运行 websocket 服务器脚本时,它拦截了来自ws://example.com:12345 的每个请求。我什至不需要在客户端调用中指定/server.php

    但我想如果你想让事情变得干净,或者你可能有几个不同的脚本,这很重要?

    无论如何,这只是在我的 locahost 中尝试 websocket 后的猜测;我根本不是 websocket 专家 :)

    【讨论】:

      【解决方案2】:

      基本上,WebSocket 定义了一个全双工单套接字连接,通过该连接可以在客户端和服务器之间发送消息。

      您应该阅读以下内容:

      http://es.wikipedia.org/wiki/WebSocket

      还有这个:

      http://www.websocket.org/

      【讨论】:

      • 是的,我知道 WebSocket 是什么。我问它是如何工作的。这不是我的问题的答案。完全没有。 :)
      【解决方案3】:

      Websocket 是持久连接(它们被设计为持久连接,尽管您仍然可以随时滥用关闭帧来重新建立连接......)。 (请记住,websocket 是有状态的,而不是无状态的 HTTP)

      因此,当您通过new WebSocket('ws://example.com:12345/server.php'); 打开 websocket 连接时,您的 web 服务器或套接字侦听脚本将接受该连接。 (网络服务器必须与您使用的代码使用相同的语言,对于 websocket,因为它们是持久连接,而不是类似 HTTP 的无状态输入输出循环......)

      然后它会读取你的握手请求并根据这些信息决定请求必须被路由到哪里。

      因此,您的路由器通常应该调用一些回调来根据指定的路径委托初始化。您通常不使用 websockets 路由到真实文件。您更多地定义某些路径以路由到它们的处理程序。

      然后您通常将您的客户端套接字映射到用户。 (例如向某个用户发送数据)

      因此,对于后续传入的数据,您只需将其与客户端状态信息一起传递给先前根据路由确定的回调。


      不过,对于您的问题,很难猜出您的问题到底是什么。如果它不能回答您的问题,请在您的问题中更准确。 它是如何工作的有点过于笼统了。

      【讨论】:

      • bwoebi,谢谢您的详细解答!我尝试从这个库运行第一个示例(“聊天”):github.com/morozovsk/websocket
      • @toprightgamedev 我看到了你的其他问题。但它仍然没有描述如何准确地设置和运行它们。
      • 我运行它们就像php -q path/to/server.php一样简单。
      • @toprightgamedev 没有回答我的问题。你们都做了什么_设置?至少,根据您提供的信息,我们无能为力。我们无法访问您的邮箱。
      • 1.我配置了防火墙并打开了一个 TCP 端口; 2. 编辑 PHP 和 HTML 文件中的主机和端口属性; 3. 将所有脚本复制到服务器; 4. 通过php -q path/to/server.php启动服务器; 5. 脚本写入控制台(在服务器端):“PHP 警告:PHP 启动:无法加载动态库 '/usr/lib/php5/20090626/mysqlnd.so' - /usr/lib/php5/20090626/mysqlnd .so:无法打开共享对象文件:第 0 行的 Unknown 中没有此类文件或目录”并继续工作; 6. 客户等待很久,一无所获。我错过了什么吗?
      【解决方案4】:

      好的,如果您的 server.php 文件正在运行,并且您可以看到它使用netstat 在端口上侦听,那么首先只需使用ws://example.com:1234 进行连接。接下来,您说“客户等待很长时间,但一无所获”如果是这种情况,握手过程很可能有问题。我第一次开始在 php 中使用套接字时遇到了同样的问题。当 javascript 连接到 websocket 时,它会在标头中发送一个特定的键,它看起来像这样:

      Sec-WebSocket-Key: 9a9dufa9dfa90fa
      

      你必须把它从标题中拉出来,在上面附加一个字符串(是的,你必须使用那个确切的字符串258EA...)然后sha1()它然后将它转换为base64,如下所示:

      if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
          $key = $match[1];
      $acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
      $acceptKey = base64_encode(sha1($acceptKey, true));
      

      接下来,您需要将其与其他一些信息一起写回套接字,以便 javascript 与服务器握手:

      $upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
                 "Upgrade: websocket\r\n".
                 "Connection: Upgrade\r\n".
                 "Sec-WebSocket-Accept: $acceptKey".
                 "\r\n\r\n";
      socket_write($the_socket, $upgrade); //$the_socket comes from socket_accept()
      

      握手完成后,在您的 javascript 中,.onopen() 函数应该触发,您可以在客户端和服务器之间来回发送数据:

      var connection = new WebSocket('ws://127.0.0.1:1234');
      connection.onopen = function () {
          console.log('Connection Opened');
          connection.send('Ping'); // Send the message 'Ping' to the server
      };
      

      【讨论】:

        猜你喜欢
        • 2014-11-14
        • 1970-01-01
        • 2017-08-17
        • 1970-01-01
        • 2019-02-01
        • 1970-01-01
        • 2019-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多