1. 保证php开启sockets,找到php.ini,找到 ;extension=sockets 去掉前面的 ;
命令行测试是否开启:php c:\...\isSockets.php
isSockets.php
<?php
if(extension_loaded('sockets')){
echo "已开启";
}else{
echo "未开启";
}
?>
2.
目前较好的开发即时通讯的框架,推荐:workerman,and swoole 。
开发中。(使用了workerman)
服务器端,启动: 命令模式shell :php your/path/server.php
注意。传输模式的设置,默认传文本。如果开发语言等功能,设置arraybuffer
<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
use Workerman\Protocols\Websocket;
// 创建一个Worker监听2345端口,使用http协议通讯
$http_worker = new Worker("websocket://127.0.0.1:8000");
// $http_worker = new Worker("websocket://172.25.204.1:8000");
// 启动4个进程对外提供服务
$http_worker->count = 4;
$global_uid = 0;
$client = []; //保存客户端信息
$out = [];
// 当客户端连上来时分配uid,并保存连接,并通知所有客户端
function handle_connection($connection)
{
global $http_worker, $global_uid;
// 为这个连接分配一个uid
$connection->uid = ++$global_uid;
}
// 当客户端发送消息过来时,转发给所有人
function handle_message($connection, $data)
{
global $http_worker,$client,$out;
// $connection->websocketType = Websocket::BINARY_TYPE_BLOB; //传输文本
$connection->websocketType = Websocket::BINARY_TYPE_ARRAYBUFFER; //设置传输二进制数据
foreach($http_worker->connections as $conn)
{
$conn->send($data);
// $conn->send('users:'.json_encode($out));
// $conn->send($data);
// $conn->send($connection->uid);
}
}
// 当客户端断开时,广播给所有客户端
function handle_close($connection)
{
global $http_worker,$client,$out;
//退出的时候删除用户
foreach ($out as $key => $value) {
if ($value["id"] == $connection->uid) {
// echo "delet array";
// unset($out[$key]);
}
}
foreach($http_worker->connections as $conn)
{
$conn->send("user[{$connection->uid}] 退出聊天室");
}
}
$http_worker->onConnect = 'handle_connection';
$http_worker->onMessage = 'handle_message';
$http_worker->onClose = 'handle_close';
Worker::runAll();
客户度:
var ws = new WebSocket("ws://127.0.0.1:8000"); //对应的域名地址和端口
ws.binaryType = 'arraybuffer'; //设置客户端传数据的模式
接收数据
// onmessage 通讯
// 收到的是 blob 数据
ws.binaryType = "blob";
ws.onmessage = function (res) {
if(typeof(res.data) == "string"){
console.log('get data is string');
}
if((res.data) instanceof Blob) { // 判断是否是二进制数据类型,并处理二进制信息
console.log('get data is Blob...');
var data_blob = new Blob([res.data],{type:"audio/wav"});//接收文件,并还原可播放音频文件
}
dataRec = data_blob;
// 处理接收到的blob数据;
var reader = new FileReader();
// var firstBlob = res.data;
// reader.readAsBinaryString(firstBlob); //该方法被w3c剔除,用readAsArrayBuffer替代。
// reader.readAsArrayBuffer(res.data);
var s = reader.readAsText(res.data); //
reader.addEventListener("loadend",function(res){
var buffer = res.currentTarget.result;
if (buffer.indexOf("say")!=-1) {
var said = $.parseJSON(buffer);
saidHtml = `<div>${said.userName} 说 : ${said.content}</div>`;
$("#chatContainer").append(saidHtml+'<br/>');
}else if(buffer.indexOf("退出聊天")!=-1){
saidHtml = `<div>${buffer}</div>`;
$("#chatContainer").append(saidHtml+'<br/>');
}
else{
html = `<div id="${msgId}" class="userRec">发来了语音</div>`;
$("#chatContainer").append(html+'<br/>');
return;
}
})
}
尚未完善。待更。
参考文档资料。
ws.onmessage = function(event){ if (event.data instanceof Blob) { var blob = event.data; //先把blob进行拆分,第一个字节是标识 var newblob=blob.slice(0,1); //js中的blob没有没有直接读出其数据的方法,通过FileReader来读取相关数据 var reader = new FileReader(); reader.readAsBinaryString(newblob); var imgFlag; // 当读取操作成功完成时调用. reader.onload = function(evt){ if(evt.target.readyState == FileReader.DONE){ var imgFlag = evt.target.result; if(imgFlag=='@'){ img=document.getElementById('er'); }else if(imgFlag=='A'){ img=document.getElementById('photo'); }else{ img=document.getElementById('photo'); } newblob=blob.slice(1,blob.size); window.URL = window.URL || window.webkitURL; var source = window.URL.createObjectURL(newblob); img.src=source; } } }
