在網上百度了好多關于這一塊的,都沒有找到完整的教程,這個是我自己寫,完完全全可以實現,分享出來給需要的人
PHPSocket.IO手冊鏈接:http://m.wtbis.cn/phpsocket_io
1.安裝
cd到項目的根目錄,執(zhí)行安裝
composer require workerman/phpsocket.io
2.入口文件
也是在項目根目錄,創(chuàng)建server.php文件,寫入下面代碼
<?php
define('APP_PATH', __DIR__ . '/application/');
define('BIND_MODULE','socketio/Server/index');
// 加載框架引導文件
require __DIR__ . '/thinkphp/start.php';
3.創(chuàng)建控制器文件,也是第2個步驟的socketio/Server/index
├─application 應用目錄
│ ├─socketio 新創(chuàng)建目錄
│ │ ├─controller
│ │ │ ├─Server.php 啟動文件
4.在Server.php文件寫入下面代碼
<?php
namespace app\socketio\controller;
require_once VENDOR_PATH . "workerman/phpsocket.io/src/autoload.php";
use Workerman\Worker;
use Workerman\Timer;
use PHPSocketIO\SocketIO;
use Workerman\Protocols\Http\Request;
use Workerman\Connection\TcpConnection;
class Server
{
public function index()
{
// 全局數組保存uid在線數據
$uidConnectionMap = array();
// 記錄最后一次廣播的在線用戶數
$last_online_count = 0;
// 記錄最后一次廣播的在線頁面數
$last_online_page_count = 0;
$io = new SocketIO(2120);//socket的端口
// 客戶端發(fā)起連接事件時,設置連接socket的各種事件回調
$io->on('connection', function($socket){
// 當客戶端發(fā)來登錄事件時觸發(fā)
$socket->on('login', function ($uid)use($socket){
global $uidConnectionMap, $last_online_count, $last_online_page_count;
// 已經登錄過了
if(isset($socket->uid)){
return;
}
// 更新對應uid的在線數據
$uid = (string)$uid;
if(!isset($uidConnectionMap[$uid]))
{
$uidConnectionMap[$uid] = 0;
}
// 這個uid有++$uidConnectionMap[$uid]個socket連接
++$uidConnectionMap[$uid];
// 將這個連接加入到uid分組,方便針對uid推送數據
$socket->join($uid);
$socket->uid = $uid;
// 更新這個socket對應頁面的在線數據
//$socket->emit('update_online_count', "當前<b>{$last_online_count}</b>人在線,共打開<b>{$last_online_page_count}</b>個頁面");
});
// 當客戶端斷開連接是觸發(fā)(一般是關閉網頁或者跳轉刷新導致)
$socket->on('disconnect', function () use($socket) {
if(!isset($socket->uid))
{
return;
}
global $uidConnectionMap, $io;
// 將uid的在線socket數減一
if(--$uidConnectionMap[$socket->uid] <= 0)
{
unset($uidConnectionMap[$socket->uid]);
}
});
});
// 當$sender_io啟動后監(jiān)聽一個http端口,通過這個端口可以給任意uid或者所有uid推送數據
$io->on('workerStart', function () use ($io) {
$inner_http_worker = new Worker('http://0.0.0.0:7064');//這里IP不用改變,用的內網通訊,端口不能與socket端口想通
$inner_http_worker->onMessage = function (TcpConnection $http_connection, Request $request) use ($io) {
global $uidConnectionMap;
$post = $request->post();
$post = $post ? $post : $request->get();
// 推送數據的url格式 type=publish&to=uid&content=xxxx
switch(@$post['type']){
case 'publish':
$to = @$post['to'];
$post['content'] = htmlspecialchars(@$post['content']);
// 有指定uid則向uid所在socket組發(fā)送數據
if($to){
$io->to($to)->emit('new_msg', $post['content']);
// 否則向所有uid推送數據
}else{
$io->emit('new_msg', @$post['content']);
}
// http接口返回,如果用戶離線socket返回fail
if($to && !isset($uidConnectionMap[$to])){
return $http_connection->send('offline');
}else{
return $http_connection->send('ok');
}
}
return $http_connection->send('fail');
};
$inner_http_worker->listen();
});
Worker::runAll();
}
}
5.客戶端鏈接:
<script src='http://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'></script>
var socket = io('http://laodiyuncha.com:2120');
var uid = 'user_1';//這個uid根據自己的項目自定義
socket.on('connect', function(){
socket.emit('login', uid);
});
socket.on('new_msg', function(data){
console.log('推送過來的消息:'+data);
});
6.php推送:
// 推送的url地址,使用自己的服務器地址
$push_api_url = "http://0.0.0.0:7064";
$post_data = array(
"type" => "publish",
"content" => "這個是推送的測試數據",
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $push_api_url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
curl_setopt ($ch, CURLOPT_HTTPHEADER, array("Expect:"));
$return = curl_exec ( $ch );
curl_close ( $ch );
var_export($return);
7.啟動服務
cd到項目根目錄
php server.php start 啟動
php server.php stop 停止
php server.php restart 重啟
php server.php status 當前服務狀態(tài)
注意點:
一定要開放2120和7064端口,否則連接不了,會顯示跨域,你也可以定義其他端口
項目根目錄不是public,指的是public同級目錄
??