anjia / blog

博客,积累与沉淀
107 stars 4 forks source link

Vue-Socket.io #41

Open anjia opened 5 years ago

anjia commented 5 years ago

Vue-Socket.io 是一个 Vuejs 的 socket.io 集成。

https://github.com/MetinSeylan/Vue-Socket.io

anjia commented 5 years ago

Socket.IO

它是一个 JavaScript framework。

支持实时、双向和基于事件的通信。它适用于每个平台、浏览器和设备,可靠性和速度也不错。

Socket.IO enables real-time, bidirectional and event-based communication.

  1. real-time analytics 实时分析
    • 把数据实时推送到客户端,以备实时分析
  2. instant messaging and chat 即时消息和聊天
    • 实时聊天~
  3. binary streaming 二进制流
    • 可来回发送各种 blob:image, video, autio
  4. document collaboration 文档合作
    • 可多用户编辑文档

https://socket.io/

入门

Sockets(套接字)是大多数 real-time chat systems 用的解决方案,能在 client 和 server 之间提供双向通信通道。这样 server 就能给 clients 推送消息了。

通常的思路是:客户端发送了个消息,服务器取到它,再讲它推送到所有其他连接的 clients。

当然,也可以轮询服务器、跟踪 timestamps,但效率比较低

1. 使用 Socket.IO

Socket.IO 由两部分组成:

2. Emitting events

Socket.IO 背后的思想是你可以 send 和 receive 任何 events,数据也不限。 任何能 encode 成 JSON 的数据都可以,binary data 也可以。

3. Broadcasting

目的:从 server 把事件 emit 到其它所有的 users

完整代码

client 端的代码示例:

const socket = io();
// 1.会加载 socket.io-client, 且会连接
//    defaults to trying to connect to the host that serves the page

const msgIpt = $('#m');

$('form').submit(function(){
    socket.emit('chat message', msgIpt.val());
    // 2.发送事件 'chat message'

    msgIpt.val('');
    return false;
});

socket.on('chat message', function(msg){
    $('#messages').append($('<li>').text(msg));
});// 3.接收服务器转发/推送的消息

server 端的代码示例:

var app = require('express')();
var http = require('http').Server(app);

var io = require('socket.io')(http);
// 1.初始化一个新的 socket.io 实例, 参数是 HTTP server 对象

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');

  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
  // 3.每个 socket 都有一个 'disconnect' 事件
  // ...每次刷新页面,都是先 disconnect 再 connect

  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
    io.emit('chat message', msg); // 5.向所有人发送该消息
  });// 4.自定义的事件 'chat message'
});
// 2.监听 'connection' 事件,当有进来的 sockets 时会触发

http.listen(3000, function(){
  console.log('listening on *:3000');
});

https://socket.io/get-started/chat

anjia commented 5 years ago

WebSockets

Web SocketsHTML5 诸多技术中的一个。

the WebSocket API ~ WebSockets

先来看下它和 Ajax 的区别。

Ajax WebSocket
从 client 主动发出请求 server 和 clients 之间双向消息推送
受 origin 限制 允许 cross-origin 通信

对 WebSockets 的理解,可以从以下几个方面:

ws是一个升级了的http请求 eg.在浏览器内聊天,就非常适合用 WebSocket

当浏览器不支持 WebSocket 时,可以使用一些回退传输:

anjia commented 5 years ago

Socket.IO

Socket.IO 是对 WebSocket 的封装&扩展。可以无缝回退~

Socket.IO,一套 API,可以:

  1. WebSocket event handling. 进一步封装&扩展
    • 支持常规的 event, 即 native Websocket API 提供的
      • eg.connect, disconnect, message
    • 新增了on(),封装了每个 event type,类似 Node 那样
      • 可以给事件个 name
    • 让有些场景下的使用更简单了
      • eg.心跳检测、重连、服务器广播 etc.
  2. fallback transports. 回退处理。使用特征检测,自动切换于以下
    • WebSocket
    • Flash Socket
    • AJAX long-polling
    • AJAX multipart streaming
    • IFrame
    • JSONP polling
  3. server side solution. 服务器端的处理
    • 它为 Node.js 提供了个套 API,长的很像 client 端的

所以,Socket.IO 不仅仅是对 WebSocket 的封装,它是一个功能更全面的库

anjia commented 5 years ago

Socket.IO vs WebSockets

在网上查的资料:了解它两的不同,以便技术选型时参考

Socket.IO

  1. 当在 send/emit 消息时,可以指定一个 event name
  2. 当要从 server 推送消息到所有 clients 时,可以很方便的实现
    • clients 监听相同的 event name 即可
    • 但是 websocket,需要维护一个连接到所有 clients 的数组,遍历,再发送给各个 client
  3. 它简化了 WebSocket 的使用。如2中所说
  4. 也提供了当浏览器/服务器不支持 WebSocket 时的机制
    • fail-overs to other protocols

https://stackoverflow.com/questions/10112178/differences-between-socket-io-and-websockets https://davidwalsh.name/websocket


https://codeburst.io/why-you-don-t-need-socket-io-6848f1c871cd

浏览器+服务器之间的异步通信 asynchronous communication between browsers and servers

作者指出: 虽然 Socket.IO 的兼容性特别地好,但它的成本比较高。诸如:

Socket.IO 实际是两个库

Socket programming 也介绍了套接字编程

另外,WebSockets 并不是真正的 sockets,虽然二者非常接近

anjia commented 5 years ago

Socket.IO API

server

可用选项:

{
    'path': '/socket.io'  // 要捕获的路径名称。默认是`/socket.io`
    'serveClient': true,  // 是否提供客户端文件
    'adapter': '[Adapter]', // 要使用的适配器。默认是 Adapter 的实例,Adapter 是 socket.io 附带的,是基于内存的。请参阅socket.io-adapter
    'origins': '*',       // 允许的 origins
    'parser': '-'         // 要用的解析器。 默认是 Parser 的实例,Parse 也是 socket.io 附带的。详见 socket.io-parser
}
// 列出的,均为默认值

底层 Engine.IO 服务器的可用选项:

// 列出的,均为默认值
{
    'pingTimeout': 5000,   // ms, 多长时间之内,如果没有 pong 包,就会考虑关闭连接
    'pingInterval': 25000,  // ms, 多长时间发送一个新的 ping 包 
    'upgradeTimeout': 10000, // ms, 多长时间之内,取消未完成的传输升级(即会直接降级为 http 轮询或者其它非 websocket)
    'maxHttpBufferSize': 10e7, // 在关闭会话之前,消息可以有多少字节或字符(规避 DoS)
    'allowRequest': '',  // 一个函数,第一个参数是接收到的给定的握手或升级请求,可以决定是否继续;第二个参数是一个函数,会传入已确定的信息,并调用 `fn(err, success)`,`success`是一个布尔值,false 意味着请求被拒绝,err 是一个错误码
    'transports': ['polling', 'websocket'],  // 允许连接的传输
    'allowUpgrades': true,    // 是否允许传输升级
    'perMessageDeflate': true,  // WebSocket permessage-deflate 扩展的参数(参见 ws module api 文档)。设置为 false 表示禁用
    'httpCompression': true, // 控制轮询传输的 http 压缩(详见 zlib API 文档)。设置为 false 表示禁用
    'cookie': 'io',   // HTTP cookie 的名字,包含 client sid-会作为握手响应 headers 的一部分被发送。设置为 false 表示不发送
    'cookiePath': '/',  // cookie 选项的 path。如果是 false,不发送任何 path, 这意味着浏览器只会在 engine.io 上附加 cookie,path 是 `/engine.io`。设置为 false 表示不在所有的请求上保存 cookie
    'cookieHttpOnly': true, // true 表示 cookie 是 HttpOnly 的,即不能被客户端的 API 访问到。如果上述两个选项 cookie 和 cookiePath 都是 false 的话,那这项不会起作用
    'wsEngine': 'ws'   // 使用的哪种 WebSocket server 实现。指定的模块,比如符合 ws 接口(详见 ws module API 文档)。默认是 ws。也可以安装 uws 模块来使用 c++ 插件
}

在以上选项中:

其它:

// 接收事件 socket.on(eventName, callback)


https://socket.io/docs/server-api/

### client
```js
import io from 'socket.io-client'

// 创建一个 Socket Manager
const socket = io(url, {   // url 默认是 window.location
    path: '/socket.io',    // String.
    query: {},     // Object. 查询参数
    parser: ;       // 使用的解析器。默认是 socket.io 自带的 Parser。详见 socket.io-parser
    reconnection: true,           // Boolean. 是否自动重新连接。默认 true
    reconnectionAttempts: 1,      // Number. 尝试重新连接的次数。默认 Infinity
    reconnectionDelay: 1000,      // Number. 尝试重新连接之前的等待多长。默认 1000。但它受随机因子影响,比如默认的初始延时会介于 500-1500 ms
    reconnectionDelayMax: 5000,   // Number. 重新连接之间等待的最长时间。默认 5000。每次尝试都将重新连接延迟增加2倍以及随机化
    randomizationFactor: 0.5,     // Number. 默认 0.5。 0 <= randomizationFactor <= 1
    timeout: 20000,               // Number. 连接超时, 默认 20000。  如果多长时间之内连接还没建成功,则认为失败,会触发 connect_error 和 connect_timeout 事件。进而触发重连机制
    autoConnect: true,            // Boolean. 默认是 true。如果设置成 false,则必须手动调用 manager.open,在你觉得合适的时候

    transports: ['websocket', 'polling']    // Array. 要尝试的传输列表(按序)。默认是 ['polling', 'websocket']。
    upgrade: true,  // Boolean.
    forceJSONP: true,  // Boolean. 轮询传输时强制 JSONP 
    jsonp: true, // Boolean. 轮询时...
    // ....
})
/**
 * options 对象可接收的参数:
 * - io.Manager: https://github.com/socketio/socket.io-client/blob/master/docs/API.md#new-managerurl-options
 * - engine.io-client: https://github.com/socketio/engine.io-client#methods
 */

https://github.com/socketio/socket.io-client/blob/master/docs/API.md

anjia commented 5 years ago

移动端,当浏览器最小化之后

anjia commented 5 years ago

Socket.IO vs Centrifugo

异同点 Socket.IO Centrifugo
设置 ping-pong 在 Server 端 在 Client 端
浏览器不可见时 依然有 ping-pong 没 ping-pong 了
.disconnect() 连接断了,但是 event_name 还在;所以再次.connect()时不用再监听事件 连接断了,也会取消订阅;所以再次.connect()时需要重新订阅 channel
server 判断 client 是否在线 客户端.close()/.disconnect() 客户端.unsubscribe()即可
断网重连后 ws 会自动连接,功能恢复 ws 会自动连接&自动订阅,功能恢复

ws 的注意事项

功能:

场景:

兼容只测了功能,未发现异常 但未深入到库的底部协议/连接机制

copywrite commented 3 years ago

WebSockets

Web SocketsHTML5 诸多技术中的一个。

the WebSocket API ~ WebSockets

先来看下它和 Ajax 的区别。

Ajax WebSocket 从 client 主动发出请求 server 和 clients 之间双向消息推送 受 origin 限制 允许 cross-origin 通信 对 WebSockets 的理解,可以从以下几个方面:

  • 协议可以使用ws(安全)和wss(不安全)
  • 它是在单个 TCP socket(套接字)上进行通信的
  • onmessage事件,消息体必须是字符串

ws是一个升级了的http请求 eg.在浏览器内聊天,就非常适合用 WebSocket

当浏览器不支持 WebSocket 时,可以使用一些回退传输:

  • Flash。但它的缺点是,有些客户端是没有装/不能装 Flash
  • Ajax 长轮询

    • 有效,但并未针对消息发送做优化
    • 所以,并不是最佳方法

ws安全还是wss是安全的