Swoole从入门到入土(19)——WebSocket服务器[文件传输]
要利用WebSocket进行文件传输,我们需要讨论两种情况,分别是:发送方可以是客户端,和 发送方是服务端。
1、发送方是客户端
1)服务端接收
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
switch ($frame->opcode)
{
case 0x09:
$pongFrame = new Swoole\WebSocket\Frame;
$pongFrame->opcode = WEBSOCKET_OPCODE_PONG;
$server->push($frame->fd, $pongFrame);
echo "pone\n";
break;
case 0x08:
echo "Close frame received: Code {$frame->code} Reason {$frame->reason}\n";
break;
case 0x01:
echo "Text string\n";
break;
case 0x02:
echo "Binary data\n";
//服务端在这里接收,$frame->data即是客户端发过来的文件二进制数据
$server->push($frame->fd,$frame->data,WEBSOCKET_OPCODE_BINARY);
break;
default:
$server->push($frame->fd, $frame->data);
break;
}
});
2) 客户端(Javascript)发送
form.on('submit(fileSend)',function(data){
var jqFile=$("#file");
try
{
var file=jqFile.get(0).files[0];
var filesize=file.size;
var reader=new FileReader();
//reader.readAsBinaryString(file);
//这里可以通过slice函数,对文件进行分割,多次传送
var blob=file.slice(0,filesize);
reader.readAsArrayBuffer(blob);
reader.onload=function(e){
var arrBuf=e.target.result;
oWs.send(arrBuf);
};
}catch(e){
layer.msg("文件异常");
}
return false;
});
到这里,有一点需要进行强调,利用slice对文件进行分割发送,多次send将文件内容多次传输到接收端,websocket协议会保证先发的先到达,后发的后达到,不会存在乱序问题。
2、发送方是服务端
1) 服务端发送
上面的例子已经提到,利用服务端的push可以将文件二进制数据推送到客户端。
$server->push($frame->fd,$frame->data,WEBSOCKET_OPCODE_BINARY);
2)客户端接收
这一部分,就有比较多的讨论内容。首先,服务端将文件数据以二进制的形式传递到客户端,客户端可以选择以blob或arraybuffer方式接收。
下面我们指定以arraybuffer方式接收:
oWs=new WebSocket(url);
oWs.binaryType="arraybuffer";
接下来,如果arraybuffer存储的是字符串数据,我们面临的就是要判断这些二进制数是是GBK还是UTF-8,并转成对应的string。
//传入arraybuffer,判断是否utf8
function IsTextUtf8(inputStream)
{
var byteArray=new Uint8Array(inputStream); var encodingBytesCount = 0;
var allTextsAreASCIIChars = true ; for ( var i = 0; i < byteArray.length; i++)
{
var current = byteArray[i]; if ((current & 0x80) == 0x80) allTextsAreASCIIChars = false ; if (encodingBytesCount == 0)
{
if ((current & 0x80) == 0) continue ; if ((current & 0xC0) == 0xC0)
{
encodingBytesCount = 1;
current <<= 2; while ((current & 0x80) == 0x80)
{
current <<= 1;
encodingBytesCount++;
}
}
else
{
// Invalid bits structure for UTF8 encoding rule.
return false ;
}
}
else
{
if ((current & 0xC0) == 0x80)
{
encodingBytesCount--;
}
else
{
return false ;
}
}
} if (encodingBytesCount != 0) return false ; return !allTextsAreASCIIChars;
}
//传入arraybuffer,判断是否GBK
function IsTextGbk(inputStream)
{
var byteArray=new Uint8Array(inputStream);
var nBytes = 0;//GBK可用1-2个字bai节编码,中文两个 ,英文一个
var chr = byteArray[0];
var bAllAscii = true; //如果全部都是ASCII,
for (var i = 0; i<byteArray.length; i++)
{
chr = byteArray[i];
if ((chr & 0x80) != 0 && nBytes == 0) // 判断是否ASCII编码,如果不是,说明有可能是GBK
{
bAllAscii = false;
}
if (nBytes == 0)
{
if (chr >= 0x80)
{
if (chr >= 0x81 && chr <= 0xFE)
{
nBytes = +2;
}
else
{
return false;
} nBytes--;
}
}
else
{
if (chr < 0x40 || chr>0xFE) return false;
nBytes--;
}//else end
} if (nBytes != 0) return false; if (bAllAscii) return true; return true;
}
/*
以对应字符集读出arraybuffer的内容并转为字符串
u:arraybuffer
f:回调函数,参数为string
encoding:可选gbk和utf-8
*/
function ab2str(u,f,encoding) {
var b = new Blob([u]);
var r = new FileReader();
r.readAsText(b, encoding);
r.onload = function (){if(f)f.call(null,r.result)}
}
oWs.onmessage=function(e){
var d;
if(typeof e.data=="object")
{
if(IsTextUtf8(e.data))
{
ab2str(e.data,function(str){
d="接收UTF-8:"+str;
},"utf-8");
return;
}
else if(IsTextGbk(e.data))
{
ab2str(e.data,function(str){
d="接收GBK:"+str;
},"gbk");
return;
}
else
{
var arr=new Uint8Array(e.data);
var str='';
for(var i=0;i<arr.length;i++)
{
str+=String.fromCharCode(arr[i]);
}
d="接收对象埂进制数据:"+str;
}
}
else d="接收文本数据:"+e.data;
};
以上,就是关于文件传输的基本操作。我们可以设定自己的机制,连续传输图片数据,不断画到canvas上,造成小电影即视感;或者采用对传输的二进制数据进行base64编码方法进行传递。办法有很多,期待大家多多练习。本章到此结束。
完整的代码,大家可以看这里:传送门
--------------------------- 我是可爱的分割线 ----------------------------
最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。
Swoole从入门到入土(19)——WebSocket服务器[文件传输]的更多相关文章
- Linux入门(五)linux服务器文件远程管理
1 使用filezila远程管理linux服务器文件 filezila下载地址:https://filezilla-project.org/ filezila默认只能登录普通用户,如果想要root用 ...
- QT从入门到入土(三)——文件的读写操作
引言 文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处 理而开发的,所以文件读写是应用程序开发的一个基本功能. Qt 提供了两种读写纯文本文件的基本方法: 用 QFi ...
- Web服务器文件传输程序客户端程序实现
1. 客户端程序--主函数 客户端主程序的流程图如下: 主程序主要是分析输入的命令,根据不同命令调用不同的函数处理或者进行出错处理,函数代码如下: #include "common.h&qu ...
- Swoole学习(五)Swoole之简单WebSocket服务器的创建
环境:Centos6.4,PHP环境:PHP7 服务端代码 <?php //创建websocket服务器 $host = '0.0.0.0'; $port = ; $ws = new swool ...
- swoole创建websocket服务器
目录 1 安装准备 1.1 安装swoole前必须保证系统已经安装了下列软件 1.2 下载并解压 1.3 编译安装成功后,修改php.ini 2 构建Swoole基本实例 2.1 tcp服务器实例 2 ...
- 04.swoole学习笔记--webSocket服务器
<?php //创建webSocket服务器 $serv=); //获取请求 //on //open 建立连接 $serv:服务器 $request:客户端信息 $serv->on('op ...
- Erlang cowboy websocket 服务器
Erlang cowboy websocket 服务器 原文见于: http://marcelog.github.io/articles/erlang_websocket_server_cowboy_ ...
- 用C语言实现websocket服务器
Websocket Echo Server Demo 背景 嵌入式设备的应用开发大都依靠C语言来完成,我去研究如何用c语言实现websocket服务器也是为了在嵌入式设备中实现一个ip camera的 ...
- Hexo结合Stun静态博客搭建从入门到入土
摘要 安装npm,安装hexo相关依赖,安装主题stun 修改hexo配置,修改stun配置,部署到github,gitee实现静态访问 给博客加上全局搜索,访问量统计 hexo博客编写模板 tips ...
- WebSocket服务器
//创建websocket 服务器 ws_server.php //https://wiki.swoole.com/wiki/page/479.html //创建websocket服务器对象,监听0 ...
随机推荐
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.11.26)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- [转帖]被误解的CPU利用率、超线程、动态调频 —— CPU 性能之迷 Part 1
https://blog.mygraphql.com/zh/notes/hw/hyper-threading/ 引 性能测试.压力测试.业务系统性能容量评估.这 3 件事,可以认为是大部分程序员/软件 ...
- [转帖]容器环境的JVM内存设置最佳实践
https://cloud.tencent.com/developer/article/1585288 Docker和K8S的兴起,很多服务已经运行在容器环境,对于java程序,JVM设置是一个重要的 ...
- [转帖]Linux权限详解(chmod、600、644、666、700、711、755、777、4755、6755、7755)
https://www.cnblogs.com/monjeo/p/12191673.html 权限简介Linux系统上对文件的权限有着严格的控制,用于如果相对某个文件执行某种操作,必须具有对应的权限方 ...
- Python学习之十八_获取神通数据库所有的表数据量
Python学习之十八_获取神通数据库所有的表数据量 背景 今天想获取一下所有数据库的表信息.但是发现神通数据库的系统表里面的表信息不正确 无法获取实际意义的表信息. 联系了下神通数据库的原厂高手. ...
- [转帖]xfs_repair命令详解
https://bbs.qunyingkeji.com/2052/ 1.现状 目前网上出现大量的主机输入输出错误,原因是由于主机文件系统损坏.一线人员大部分采用的是umont 和 mount的方式恢复 ...
- Linux运行服务的几种方式
摘要 1. nohup & 2. screen 3. bg & disown 4. systemd 5. crontab @reboot 背景 最近一直在用linux 想着多总结一下. ...
- Linux与Windows系统字符集的简要学习
背景 最近同事反馈公司的产品再更新了mysql-8.0.31的驱动jar包后部分功能报错. 问题核心原因 研发这边石磊老师已经找到了. 结论是Mysql8.0.26之后的数据库驱动好像会识别操作系统的 ...
- PG数据库恢复简单记录
公司同事给了一个很小的数据 我这边进行备份和恢复操作 第一步 创建数据库 su - postgres #进入pg数据库的用户 psql #输入密码 登录 create user demo with p ...
- 【JS 逆向百例】有道翻译接口参数逆向
逆向目标 目标:有道翻译接口参数 主页:https://fanyi.youdao.com/ 接口:https://fanyi.youdao.com/translate_o?smartresult=di ...