要利用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. http-长连接

    1. 短链接 http1.0 -- 1个请求-响应过程会创建且1个新的连接 2. 长连接 http1.1 -- 同域下可以创建1个tcp连接,多个请求在同一个tcp上串行处理请求 http2.0 -- ...

  2. [转帖]NUMA导致的Oracle性能问题

    https://www.cnblogs.com/realcp1018/p/6903721.html 背景简介: Oracle版本:11.2.0.4 OS 版本:OEL5.8 在一次Oracle的Dat ...

  3. [转帖]oracle 11g 分区表创建(自动按年、月、日分区)

    https://www.cnblogs.com/yuxiaole/p/9809294.html   前言:工作中有一张表一年会增长100多万的数据,量虽然不大,可是表字段多,所以一年下来也会达到 1G ...

  4. Python学习之二:不同数据库相同表是否相同的比较方法

    摘要 昨天学习了使用python进行数据库主键异常的查看. 当时想我们有跨数据库的数据同步场景. 对应的我可以对不同数据库的相同表的核心字段进行对比. 这样的话能够极大的提高工作效率. 我之前写过很长 ...

  5. [转帖]shell 实现行转列、列转行的几种方法

    目录 shell 实现行转列.列转行的几种方法 awk 行转列 xargs 行转列 tr 列转行 参考资料 shell 实现行转列.列转行的几种方法 awk 行转列 以空格为分隔符 awk -F &q ...

  6. [转帖] Linux文本命令技巧(下)

    https://www.cnblogs.com/codelogs/p/16060108.html 简介# 前一篇介绍了Linux中一些基本的文本命令与使用技巧,但是结合场景过少,本篇结合工作中一些常见 ...

  7. 物联网浏览器(IoTBrowser)-Web串口自定义开发

    物联网浏览器(IoTBrowser)-Web串口自定义开发 工控系统中绝大部分硬件使用串口通讯,不论是原始串口通讯协议还是基于串口的Modbus-RTU协议,在代码成面都是使用System.IO.Po ...

  8. XJTU少年班+自动化钱学森班+电气工程辅修专业课笔记合集

    通过百度网盘分享的文件:笔记整理链接:https://pan.baidu.com/s/1BrHQ1EqvlQlbWqpD5h_6Sg?pwd=shsg 提取码:shsg复制这段内容打开「百度网盘APP ...

  9. 【图论,网络流】CF1525F Goblins And Gnomes

    Problem Link 你在打怪.你有一个 \(n\) 个点 \(m\) 条边的 DAG,接下来会有 \(k\) 波怪来袭,第 \(i\) 波怪有 \(i\) 个,它们会各自选择走一条路径,要求它们 ...

  10. 【计数,DP】CF1081G Mergesort Strikes Back

    Problem Link 现有一归并排序算法,但是算法很天才,设了个递归深度上限,如果递归深度到达 \(k\) 则立即返回.其它部分都和正常归并排序一样,递归中点是 \(\lfloor (l+r)/2 ...