使用PHP进行WebSocket通信

我会用PHP来实现WebSocket。

创建项目

请创建一个Composer项目。
如果您尚未安装Composer,请安装它。
请安装Composer。

创建一个合适的文件夹,然后使用命令行进行cd操作。然后在命令行中输入“composer init”,这样就可以创建composer.json文件。这次我们将使用Ratchet来进行开发。Ratchet可以从这个网址下载(http://socketo.me/)。然后在命令行中输入“composer require cboden/ratchet”,这样就可以开始使用Ratchet了。

创建一个名为”src”的文件夹。

我将调整composer.json文件的autoload配置。
我会将composer.json文件设置如下:

{
    "autoload" : {
        "psr-4" : {
            "App\\" : "src"
        }
    },
    "require": {
        "cboden/ratchet": "^0.4.3"
    }
}

在命令行中执行`composer dump-autoload`,这将使修正后的autoload生效。

文件夹的组成如下所示。

`-- sample
    |-- src
    |-- vendor
    `-- composer.json

文件创建

在src文件夹下创建Chat.php。

<?php
namespace App;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface {

    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            $data = ['msg' => $msg];
            if ($from === $client) {
                $data['position'] = 'right';
            } else {
                $data['position'] = 'left';
            }
            $client->send(json_encode($data));
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }
}

一旦建立了WebSocket连接,就会自动执行onOpen方法。这次我们将连接添加到$this->clients中。
当客户端发送数据过来时,就会自动执行onMessage方法。这次我们将返回Json数据。

在src文件夹下创建wsServer.php。

<?php
namespace App;

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\Chat;

require dirname(__DIR__) . '\vendor\autoload.php';

$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat()
            )
        ),
    8282
    );

$server->run();

这将成为WebSocket的入口点
8282是用于WebSocket的端口。请确保防火墙允许此端口
使用刚刚创建的Chat类来运行WebSocket服务器

(3) 在HTTP服务器的公开文件夹中创建ws.html。

<html>
<head>
<title>sample</title>
<style type="text/css">
.container {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
}
.msg-log {
    width: 100%;
    height: 92%;
    vertical-align:top;
    box-sizing: border-box;
    padding: 0px;
    border: black solid 1px;
    overflow-y: scroll;
}
.input-area {
    width: 100%;
    box-sizing: border-box;
}
.msg {
    width: 90%;
    height: 8%;
    vertical-align:top;
    box-sizing: border-box;
    padding: 0px;
    float: left;
}
.btn {
    width: 10%;
    height: 8%;
    vertical-align:top;
    box-sizing: border-box;
    padding: 0px;
}
.receive-msg-left {
    border-radius: 10px;
    border: black solid 1px;
    padding: 10px;
    margin: 10px;
    display: inline-block;
    float: left;
}
.receive-msg-right {
    border-radius: 10px;
    border: black solid 1px;
    padding: 10px;
    margin: 10px;
    display: inline-block;
    float: right;
    background-color: #00FF00;
}
.br {
    clear: both;
}
</style>
<script type="text/javascript">

  var conn = "";

  function open(){

      conn = new WebSocket('ws://localhost:8282');

      conn.onopen = function(e) {
      };

      conn.onerror = function(e) {
        alert("エラーが発生しました");
      };

      conn.onmessage = function(e) {
          var data = JSON.parse(e.data);
          var divObj = document.createElement("DIV");
          if (data["position"] == "left") {
              divObj.className = 'receive-msg-left';
          } else {
              divObj.className = 'receive-msg-right';
          }
          var msgSplit = data["msg"].split('\n');
          for (var i in msgSplit) {
              var msg = document.createTextNode(msgSplit[i]);
              var rowObj = document.createElement("DIV");
              rowObj.appendChild(msg);
              divObj.appendChild(rowObj);
          }

          var msgLog = document.getElementById("msg_log");
          msgLog.appendChild(divObj);

          var br = document.createElement("BR");
          br.className = 'br';
          msgLog.appendChild(br);

          msgLog.scrollTop = msgLog.scrollHeight;

      };

      conn.onclose = function() {
          alert("切断しました");
          setTimeout(open, 5000);
      };

  }

  function send(){
      conn.send(document.getElementById("msg").value);
  }

  function close(){
      conn.close();
  }

  open();

</script>
</head>
<body>
    <div class="container">
        <div id="msg_log" class="msg-log"></div>
        <div class="input-area">
            <textarea id="msg" class="msg"></textarea>
            <button class="btn" onclick="send();" >送信</button>
        </div>
    </div>
</body>
</html>

我们正在使用conn = new WebSocket(‘ws://localhost:8282’)进行连接。其中8282是之前在wsServer.php中指定的端口。
我们使用conn.send(document.getElementById(“msg”).value)将数据发送到webSocket服务器。
当webSocket服务器有send时,conn.onmessage会自动执行。

确认动作

通过命令行,在src文件夹中使用cd命令,然后运行php wsServer.php,这样WebSocket服务器就启动了。

启动HTTP服务器并尝试在HTTP服务器的公开文件夹中打开ws.html,用浏览器访问
http://localhost/ws.html,
请分别在Chrome和Firefox中访问。

在Chrome浏览器中键入“测试Chrome”,然后点击发送按钮
在Firefox浏览器中键入“测试火狐”,然后点击发送按钮

动了

a.png
b.png

在Laravel框架中使用Ratchet

使用Ratchet库的方法在下面的文章中有详细介绍

广告
将在 10 秒后关闭
bannerAds