使用php做一个socket服务器来推送消息
环境配置
win10
apache
php5.6
环境搭建
找一个空的目录先用composer安装 phpsocket.io-for-win(windows下使用这个linux下直接使用phpsocket.io)如下,先初始化composercomposer init
然后安装workerman/phpsocket.io-for-wincomposer require workerman/phpsocket.io-for-win
安装完成后就可以开始写代码测试啦
官方示例
因为在windows下上面示例不能直接启动,需要改成两个命令窗口来运行才行,一个web服务一个socket服务不然会出现下面的提示
出现这个提示的时候上面的webserver是启动成功啦但是phpsocketio却没有成功,虽然显示的是ok。
我的示例
自己搭建web服务器,然后使用phpsocket.io服务来实现功能,代码是我在官方代码的基础上改动过的,https://github.com/zhaokeli/phpsocket 使用方法,使用git下载后
1、composer install
2、创建一个站点,站点根目录为这个目录
3、运行start-debug.bat
4、地址栏输入你访问站点的路径就可以看效果啦
消息推送
使用http实现调用api进行消息主动推送// 当$io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
$io->on('workerStart', function(){
// 监听一个http端口
$inner_http_worker = new Worker('http://0.0.0.0:2121');
// 当http客户端发来数据时触发
$inner_http_worker->onMessage = function($http_connection, $data){
global $uidConnectionMap;
$_POST = $_POST ? $_POST : $_GET;
// 推送数据的url格式 type=publish&to=uid&content=xxxx
switch(@$_POST['type']){
case 'publish':
global $io;
$to = @$_POST['to'];
$_POST['content'] = htmlspecialchars(@$_POST['content']);
// 有指定uid则向uid所在socket组发送数据
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();
// 一个定时器,定时向所有uid推送当前uid在线数及在线页面数
Timer::add(1, function(){
global $uidConnectionMap, $io, $last_online_count, $last_online_page_count;
$online_count_now = count($uidConnectionMap);
$online_page_count_now = array_sum($uidConnectionMap);
// 只有在客户端在线数变化了才广播,减少不必要的客户端通讯
if($last_online_count != $online_count_now || $last_online_page_count != $online_page_count_now)
{
$io->emit('update_online_count', "当前{$online_count_now}人在线,共打开{$online_page_count_now}个页面");
$last_online_count = $online_count_now;
$last_online_page_count = $online_page_count_now;
}
});
});
使用方法参考 https://www.workerman.net/web-sender
常用的方法api
分组
socket.io提供分组功能,允许向某个分组发送事件,例如向某个房间广播数据。
1、加入分组(一个连接可以加入多个分组)$socket->join('group name');
2、离开分组(连接断开时会自动从分组中离开)$socket->leave('group name');
向客户端发送事件的各种方法
$io是SocketIO对象。$socket是客户端连接
$data可以是数字和字符串,也可以是数组。当$data是数组时,客户端会自动转换为javascript对象。
同理如果客户端向服务端emit某个事件传递的是一个javascript对象,在服务端接收时会自动转换为php数组。
1、向当前客户端发送事件$socket->emit('event name', $data);
2、向所有客户端发送事件$io->emit('event name', $data);
3、向所有客户端发送事件,但不包括当前连接。$socket->broadcast->emit('event name', $data);
4、向某个分组的所有客户端发送事件$io->to('group name')->emit('event name', $data);
获取客户端ip$io->on('connection', function($socket)use($io){ var_dump($socket->conn->remoteAddress);});
关闭链接$socket->disconnect();