Javascript Socket.io 1.x:是否仅使用WebSocket?
出于不同的原因,我们正在开发一个只在现代浏览器(IE10+)上运行的web应用程序 我们实现的特性之一是Socket.io1.x。但是,默认情况下,Socket.io客户端尝试支持较旧的浏览器,因此它会使用长轮询启动连接,然后将其更新到WebSocket。这是浪费时间和资源,因为我们确信浏览器支持WS 我四处搜索,但只能找到与Socket.io 0.9有关的内容 最终,我找到了(Socket.io-client基于1.x分支)。这是我写的代码,似乎正在工作。但是,我想知道这是正确的还是我做错了什么:Javascript Socket.io 1.x:是否仅使用WebSocket?,javascript,websocket,socket.io,Javascript,Websocket,Socket.io,出于不同的原因,我们正在开发一个只在现代浏览器(IE10+)上运行的web应用程序 我们实现的特性之一是Socket.io1.x。但是,默认情况下,Socket.io客户端尝试支持较旧的浏览器,因此它会使用长轮询启动连接,然后将其更新到WebSocket。这是浪费时间和资源,因为我们确信浏览器支持WS 我四处搜索,但只能找到与Socket.io 0.9有关的内容 最终,我找到了(Socket.io-client基于1.x分支)。这是我写的代码,似乎正在工作。但是,我想知道这是正确的还是我做错了什
io.connect('https://...', {
upgrade: false,
transports: ['websocket']
})
奇怪的是,仅仅将transports
属性设置为只包含websockets
的数组是不够的;我还必须禁用升级
。这是正确的吗
更新
我有了一些新发现
仅当transports
设置为['websocket']
时,无论是否启用升级
,都没有任何区别。这正常吗?socket.io有两种类型的“升级”。首先(在socket.io 1.0+中),socket.io通过http轮询请求启动所有连接,并且它实际上可能只通过http请求交换一些初始数据。然后,在之后的某个时刻,它将尝试实际启动webSocket连接。webSocket连接是通过发送指定升级:webSocket
头的特定类型的http请求来完成的,然后服务器可以适当地响应是否支持webSocket。如果服务器同意升级,那么特定的http连接将“升级”到webSocket协议。此时,客户端知道webSocket受支持,并停止使用轮询http请求,从而完成对webSocket的升级
通过在客户端上执行以下操作,可以完全防止初始http轮询:
var socket = io({transports: ['websocket'], upgrade: false});
这将阻止从您自己的合作客户端轮询连接。如果要阻止任何客户端使用轮询,则可以将其添加到服务器:
io.set('transports', ['websocket']);
但是,如果在服务器上设置此选项,则最初使用http轮询连接的socket.io客户端将根本无法工作。因此,这应该只与客户端中的正确设置相匹配,这样客户端就不会以轮询开始
这将告诉两端您只想使用WebSocket,socket.io将在开始时跳过额外的http轮询。公平警告,这样做需要webSocket支持,因此排除了与尚未支持webSocket的旧版本IE兼容的可能性。如果您想保持兼容性,那么首先让socket.io处理几个http请求即可
下面是有关从http到webSocket的协议升级的更多信息 webSocket协议通过HTTP连接启动每个webSocket。所有WebSocket都是这样工作的。该HTTP连接上包含一些标头,表示浏览器“希望”升级到webSockets协议。如果服务器支持该协议,那么它会做出响应,告诉客户端它将升级到webSocket协议,然后该套接字就会从HTTP协议切换到webSocket协议。这就是webSocket连接的工作原理。因此,您看到webSocket连接以HTTP连接开始的事实是100%正常的
您可以将socket.io配置为永远不使用长轮询(如果这让您感觉更好的话),但这不会改变webSocket连接仍将以HTTP连接开始,然后升级到webSocket协议的事实,也不会提高支持webSocket的现代浏览器中的操作效率。但是,它会使您的连接在较旧的浏览器中无法工作。我想我应该添加到上面接受的答案中,好像有人想消除XHR轮询传输并立即启动WebSocket。下面的代码只是给出实现的想法:
var url = serverUrl + "/ssClients" //ssClients is the socket.io namespace
var connectionOptions = {
"force new connection" : true,
"reconnection": true,
"reconnectionDelay": 2000, //starts with 2 secs delay, then 4, 6, 8, until 60 where it stays forever until it reconnects
"reconnectionDelayMax" : 60000, //1 minute maximum delay between connections
"reconnectionAttempts": "Infinity", //to prevent dead clients, having the user to having to manually reconnect after a server restart.
"timeout" : 10000, //before connect_error and connect_timeout are emitted.
"transports" : ["websocket"] //forces the transport to be only websocket. Server needs to be setup as well/
}
var socket = require("socket.io-client")(url, connectionOptions);
socket.on("connect", function (_socket) {
logger.info("Client connected to server: " + clientName);
logger.info("Transport being used: " + socket.io.engine.transport.name);
socket.emit("join", clientName, function(_socketId) { //tell the server the client name
logger.info("Client received acknowledgement from server: " + _socketId);
logger.info("Transport being used after acknowledgement: " + socket.io.engine.transport.name);
});
});
安装服务器后,您将看到:
2015-10-23T19:04:30.076Z - info: Client connected to server: someClientId
2015-10-23T19:04:30.077Z - info: Transport being used: websocket
2015-10-23T19:04:30.081Z - info: Client received acknowledgement from server: aMH0SmW8CbiL8w5RAAAA
2015-10-23T19:04:30.081Z - info: Transport being used after acknowledgement: websocket
如果不强制传输,将看到“轮询”而不是websocket。但是,这并不仅仅发生在客户端,还必须设置服务器:
var io = require("socket.io")(server, { adapter: adapter, log: false }); //attach io to existing Express (http) server
..
io.set('transports', ['websocket']); //forces client to connect as websockets. If client tries xhr polling, it won't connect.
危险
如果客户端实际上不支持websocket协议,则不会发生连接,客户端将报告xhr轮询错误
这对我来说非常有效,因为我可以控制我的客户,所以我有权立即强制使用WebSocket,我相信这就是最初的问题所在。我希望这对其他人有所帮助…要告诉Socket.IO只使用WebSocket而不是一些XHR请求,请先将其添加到节点服务器:
io.set('transports', ['websocket']);
在客户端添加以下内容:
var socket = io({transports: ['websocket']});
这告诉Socket.IO只使用WebSocket协议,而不使用其他协议;它更干净、更快,并且在客户端和服务器端使用更少的资源
现在,您将在网络请求列表中只看到一个WebSocket连接,请记住IE9和更早版本不能使用WebSocket。我发布这个答案是因为接受的答案不正确-它将Socket.IO从长轮询AJAX升级到WebSocket与WSS协议“连接:升级”请求混淆。问题不在于WebSocket连接以HTTP启动并升级到WebSocket-怎么可能不呢但是,即使在支持WebSocket的浏览器上,Socket.IO也是以一个长轮询AJAX连接开始的,并且只有在交换了一些流量之后才进行升级。在Firefox或Chrome的开发者工具中很容易看到 问题的作者的观察是正确的。 Socket.IO中的“升级”不是指HTTP到WSS协议的升级
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
# Uninstall:
npm rm -g websocket-vs-socket.io