要利用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服务器[文件传输]的更多相关文章

  1. Linux入门(五)linux服务器文件远程管理

     1 使用filezila远程管理linux服务器文件 filezila下载地址:https://filezilla-project.org/ filezila默认只能登录普通用户,如果想要root用 ...

  2. QT从入门到入土(三)——文件的读写操作

     引言 文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处 理而开发的,所以文件读写是应用程序开发的一个基本功能. Qt 提供了两种读写纯文本文件的基本方法: 用 QFi ...

  3. Web服务器文件传输程序客户端程序实现

    1. 客户端程序--主函数 客户端主程序的流程图如下: 主程序主要是分析输入的命令,根据不同命令调用不同的函数处理或者进行出错处理,函数代码如下: #include "common.h&qu ...

  4. Swoole学习(五)Swoole之简单WebSocket服务器的创建

    环境:Centos6.4,PHP环境:PHP7 服务端代码 <?php //创建websocket服务器 $host = '0.0.0.0'; $port = ; $ws = new swool ...

  5. swoole创建websocket服务器

    目录 1 安装准备 1.1 安装swoole前必须保证系统已经安装了下列软件 1.2 下载并解压 1.3 编译安装成功后,修改php.ini 2 构建Swoole基本实例 2.1 tcp服务器实例 2 ...

  6. 04.swoole学习笔记--webSocket服务器

    <?php //创建webSocket服务器 $serv=); //获取请求 //on //open 建立连接 $serv:服务器 $request:客户端信息 $serv->on('op ...

  7. Erlang cowboy websocket 服务器

    Erlang cowboy websocket 服务器 原文见于: http://marcelog.github.io/articles/erlang_websocket_server_cowboy_ ...

  8. 用C语言实现websocket服务器

    Websocket Echo Server Demo 背景 嵌入式设备的应用开发大都依靠C语言来完成,我去研究如何用c语言实现websocket服务器也是为了在嵌入式设备中实现一个ip camera的 ...

  9. Hexo结合Stun静态博客搭建从入门到入土

    摘要 安装npm,安装hexo相关依赖,安装主题stun 修改hexo配置,修改stun配置,部署到github,gitee实现静态访问 给博客加上全局搜索,访问量统计 hexo博客编写模板 tips ...

  10. WebSocket服务器

    //创建websocket 服务器  ws_server.php //https://wiki.swoole.com/wiki/page/479.html //创建websocket服务器对象,监听0 ...

随机推荐

  1. Go-单元测试-Test

    单元测试 文件名以 _test.go 结尾 函数名以 Test 开头 函数参数固定 t *testing.T 运行单元测试 go test Demo 源文件 package unit import & ...

  2. GB18030-2022 标准学习

    GB18030-2022 标准学习 下载 https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=A1931A578FE14957104988029B08 ...

  3. [转帖]Oracle 19c 新特性|增加 VARCHAR2 数据类型的大小限制

    JiekeXuAll China Database Union2022-10-13 795 经朋友介绍,我读完 Tim Hall 于 2022 年 9 月 27 日他的博客上发表的博文.10 月 11 ...

  4. [转帖]003、体系结构之TiKV持久化

    TiKV架构和作用 数据持久化 分布式一致性 MVCC 分布式事务 Coprocessor coprocessor : 协同处理器. 可以将一些SQL计算交给TiKV处理.不需要将TiKV所有数据通过 ...

  5. [转帖]07-rsync企业真实项目备份案例实战(需求收集--服务器配置---客户端配置---报警机制---数据校验---邮件告警)

    https://developer.aliyun.com/article/885820?spm=a2c6h.24874632.expert-profile.279.7c46cfe9h5DxWK 简介: ...

  6. Nginx与Tomcat作为前端服务器的性能比较

    Nginx与Tomcat作为前端服务器的性能比较 摘要 最近总遇到使用tomcat还是使用nginx进行前端文件访问的争论 想着出差周末在酒店, 可以自己进行一下简单的测试. 希望能够对未来的工作进行 ...

  7. [转帖]jmeter压力测试

    使用jmeter 进行并发压力测试. 首先需要安装好jmeter,下面以widows操作平台为例: 1.确保电脑安装并配置好java环境:具体怎么下载和配置请自行百度: 2.登录jmeter官网htt ...

  8. Sysbench简单测试数据库性能

    摘要 先进行了一个PG数据库的测试. Mysql数据库的测试稍后跟上. 紧接着上一篇的安装, 部分文件可能需要特定路径才可以. sysbench 测试的说明 一个参数 这里稍微说一下参数的问题 sys ...

  9. 【转贴】2019.3 学习向SP打造指南 篇一:微软神器Surface产品线全系列详细介绍

    学习向SP打造指南 篇一:微软神器Surface产品线全系列详细介绍 2019-03-01 22:30:00 161点赞 699收藏 141评论 https://post.smzdm.com/p/a5 ...

  10. WebAssembly入门笔记[2]:利用Memory传递数据

    利用灵活的"导入"和"导出"机制,WebAssembly与承载的JavaScript应用之间可以很便利地"互通有无".<与JavaSc ...