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
ファイル作成
(1) 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
にコネクションを追加しています
クライアントがデータをsendしてきたら自動的にonMessageが実行されます。今回はjsonを返すようにしています
(2) 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で使うポートです。firewallで許可しているポートにしてください
先ほど作成したChatクラスを与えてWebSocketサーバーをrunします
(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サーバーにデータ送信しています
conn.onmessage
はwebSocketサーバーからsendがあった場合に自動的に実行されます
動作確認
コマンドラインで
srcフォルダにcdして
php wsServer.php
これでWebSocketサーバーが起動しました
HTTPサーバを起動し
HTTPサーバーの公開フォルダにつくったws.htmlにブラウザでアクセスしてみましょう
http://localhost/ws.html
ChromeとFirefoxでアクセスしてみましょう
Chromeでテストクロームと入力し、送信ボタンをクリックします
Firefoxでテストファイヤーフォックスと入力し、送信ボタンをクリックします
動きました
RatchetをLaravelで使う
LaravelでRatchetを使ってWebSocketする方法は下記記事に書きました
LaravelでWebSocket