Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Socket.io 1.x:是否仅使用WebSocket?_Javascript_Websocket_Socket.io - Fatal编程技术网

Javascript Socket.io 1.x:是否仅使用WebSocket?

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分支)。这是我写的代码,似乎正在工作。但是,我想知道这是正确的还是我做错了什

出于不同的原因,我们正在开发一个只在现代浏览器(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