socket.io 和 websockets 有什么区别
node.js?
它们都是服务器推送技术吗?
我觉得唯一的不同是,
socket.io 允许我通过指定事件名称来发送/发送消息。
在 socket.io 的情况下,来自服务器的消息将到达所有客户端,但对于 websockets 中的相同,我被迫保留所有连接的数组并循环通过它向所有客户端发送消息。
另外, 我想知道为什么网络检查器(如 Chrome/firebug/fiddler)无法从服务器捕获这些消息(来自 socket.io/websocket)?
请澄清这一点。
最佳答案
关于 WebSocket 和 Socket.IO 的常见误解很少:
第一个误解是使用 Socket.IO 比使用 WebSocket 容易得多,但事实并非如此。请参阅下面的示例。
第二个误解是浏览器没有广泛支持 WebSocket。有关详细信息,请参见下文。
第三个误解是 Socket.IO 将连接降级为旧浏览器的后备。它实际上假设浏览器是旧的,并开始与服务器建立 AJAX 连接,稍后在交换一些流量后在支持 WebSocket 的浏览器上升级。详情见下文。
我写了一个 npm 模块来演示 WebSocket 和 Socket.IO 的区别:
这是一个服务器端和客户端代码的简单示例 - 客户端使用 WebSocket 或 Socket.IO 连接到服务器,服务器以 1s 的间隔发送三个消息,这些消息由客户端添加到 DOM .
比较使用 WebSocket 和 Socket.IO 在 Express.js 应用程序中执行相同操作的服务器端示例:
使用 Express.js 的 WebSocket 服务器示例:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js
使用 Express.js 的 Socket.IO 服务器示例:
var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
console.error('socket.io connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');
来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js
比较在浏览器中使用 WebSocket 和 Socket.IO 的客户端示例:
使用原生 JavaScript 的 WebSocket 客户端示例:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html
使用原生 JavaScript 的 Socket.IO 客户端示例:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html
要查看网络流量的差异,您可以 run my test .以下是我得到的结果:
来自这两个请求:
(连接升级请求在开发者工具上可见,并带有 101 Switching Protocols 响应。)
来自这 6 个请求:
我在 localhost 上得到的 WebSocket 结果:
我在 localhost 上得到的 Socket.IO 结果:
快速开始:
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
打开 http://localhost:3001/在浏览器中,使用 Shift+Ctrl+I 打开开发者工具,打开 Network 选项卡并使用 Ctrl+R 重新加载页面以查看 WebSocket 版本的网络流量。
打开 http://localhost:3002/在浏览器中,使用 Shift+Ctrl+I 打开开发者工具,打开 Network 选项卡并使用 Ctrl+R 重新加载页面以查看 Socket.IO 版本的网络流量。
卸载:
# Uninstall:
npm rm -g websocket-vs-socket.io
截至 2016 年 6 月,WebSocket 可在除 Opera Mini 之外的所有设备上运行,包括高于 9 的 IE。
这是 Can I Use 上 WebSocket 的浏览器兼容性截至 2016 年 6 月:
见 http://caniuse.com/websockets获取最新信息。
关于node.js - socket.io 和 websockets 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10112178/
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性
Ruby中的Fixnum方法.next和.succ有什么区别?看起来它的工作原理是一样的:1.next=>21.succ=>2如果有什么不同,为什么有两种方法做同样的事情? 最佳答案 它们是等价的。Fixnum#succ只是Fixnum#next的同义词。他们甚至在thereferencemanual中共享同一block. 关于ruby-Ruby中.next和.succ的区别,我们在StackOverflow上找到一个类似的问题: https://stacko