Ita*_*Ale 37 javascript websocket socket.io
我们正在开发一个仅在现代浏览器(IE10 +)上运行的Web应用程序,原因各不相同.
我们实现的功能之一是Socket.io 1.x. 但是,默认情况下,Socket.io客户端会尝试支持较旧的浏览器,因此它会启动与长轮询的连接,然后将其更新到WebSockets.这是浪费时间和资源,因为我们知道浏览器支持WS.
我一直在搜索,我只能找到这个wiki页面,但是,它是关于Socket.io 0.9的.
最后,我找到了engine.io-client的文档(Socket.io-client基于1.x分支).这是我编写的代码,似乎正在运行.但是,我想知道它是否正确或者我做错了什么:
io.connect('https://...', {
upgrade: false,
transports: ['websocket']
})
Run Code Online (Sandbox Code Playgroud)
奇怪的是,仅仅将transports
属性设置为数组websockets
是不够的; 我也不得不禁用upgrade
.它是否正确?
我做了一些新的发现.
随着transports
设置为['websocket']
只,它没有任何区别阉羊upgrade
被启用.这是正常的吗?
jfr*_*d00 56
socket.io发生了两种类型的"升级".首先(在socket.io 1.0+中),socket.io启动所有与http轮询请求的连接,它实际上可能只用一个http请求交换一些初始数据.然后,在此之后的某个时刻,它将尝试实际启动webSocket连接.webSocket连接是通过发送指定upgrade: websocket
标头的特定类型的http请求来完成的,然后服务器可以适当地响应它是否支持websocket.如果服务器同意升级,则该特定http连接被"升级"为webSocket协议.此时,客户端知道支持webSocket并且它停止使用轮询http请求,从而完成其upgrade
对webSocket的控制.
您可以通过在客户端上执行此操作来完全阻止初始http轮询:
var socket = io({transports: ['websocket'], upgrade: false});
Run Code Online (Sandbox Code Playgroud)
这将阻止来自您自己的合作客户端的轮询连接.如果要阻止任何客户端使用轮询,则可以将其添加到服务器:
io.set('transports', ['websocket']);
Run Code Online (Sandbox Code Playgroud)
但是,如果在服务器上设置此项,则最初使用http轮询连接的socket.io客户端根本不起作用.因此,这应该只与客户端中的正确设置匹配,以便客户端永远不会以轮询开始.
这将告诉两端你只想使用webSockets而socket.io将在开头跳过额外的http轮询.公平的警告,这样做需要webSocket支持,所以这排除了与尚未支持webSocket的旧版IE兼容.如果你想保留兼容性,那么让socket.io最初做几个http请求.
以下是从http到webSocket的协议升级的更多信息.
webSockets协议使用HTTP连接启动每个webSocket.这就是所有webSockets的工作方式.该HTTP连接包含一些标题,表明浏览器"喜欢"升级到webSockets协议.如果服务器支持该协议,则它会响应告知客户端它将升级到webSocket协议,然后该套接字将从HTTP协议切换到webSocket协议.这就是webSocket连接的设计方式.因此,您看到以HTTP连接开头的webSocket连接的事实是100%正常.
您可以将socket.io配置为永远不会使用长轮询,如果这让您感觉更好,但这不会改变webSocket连接仍将以HTTP连接开始,然后升级到webSocket协议并且不会改善支持webSockets的现代浏览器的操作效率.但是,它会使您的连接无法在旧版浏览器中使用.
Nic*_*ele 29
要告诉Socket.IO仅使用WebSocket而不是首先使用几个XHR请求,只需将其添加到节点服务器:
io.set('transports', ['websocket']);
Run Code Online (Sandbox Code Playgroud)
并在客户端添加此:
var socket = io({transports: ['websocket']});
Run Code Online (Sandbox Code Playgroud)
这告诉Socket.IO只使用WebSocket协议而不是别的; 它更干净,更快,并且在客户端和服务器端使用更少的资源.
现在,您只会在网络请求列表中看到单个WebSocket连接,请记住IE9及更早版本不能使用WebSocket.
rsp*_*rsp 22
我发布了答案,因为接受的答案是不正确的 - 它将Socket.IO从长轮询AJAX升级到WebSocket与WSS协议"连接:升级"请求混淆.问题不在于WebSocket连接是以HTTP身份启动并升级到WebSocket - 它怎么可能不是? - 但是,即使在支持WebSocket的浏览器上,Socket.IO也会以长轮询AJAX连接开始,并且只在交换一些流量后才进行升级.在Firefox或Chrome的开发者工具中很容易看到.
这个问题的作者在他的观察中是正确的.Socket.IO中的"升级"并不是指HTTP到WSS协议升级,因为它经常被误解,而是指从长轮询AJAX连接升级到WebSocket的Socket.IO连接.如果您已经开始使用WebSocket(这不是默认设置),那么升级false无效,因为您不需要升级.如果您从轮询开始并禁用升级,那么它将保持这种状态,并且不会升级到WebSocket.
如果你想避免从长轮询开始,请参阅arnold和Nick Steele的答案.我将更详细地解释发生了什么.
这是我在使用简单的WebSocket和Socket.IO应用程序的实验中观察到的:
从这2个请求:
(连接升级请求在具有101个交换协议响应的开发人员工具上可见.)
从这6个请求中:
我在localhost上获得的WebSocket结果:
我在localhost上得到的Socket.IO结果:
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
Run Code Online (Sandbox Code Playgroud)
并遵循限制.要卸载:
# Uninstall:
npm rm -g websocket-vs-socket.io
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅此答案.
我认为我应该添加上面接受的答案,好像有人想要消除XHR轮询传输并立即启动websockets.下面的代码只是为了说明实现:
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);
});
});
Run Code Online (Sandbox Code Playgroud)
设置服务器后,您将看到:
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
Run Code Online (Sandbox Code Playgroud)
如果你不强制运输,你会看到"轮询"而不是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.
Run Code Online (Sandbox Code Playgroud)
危险
如果客户实际上并没有支持WebSocket协议,连接不会发生,并在客户端将报告xhr poll error
.
这对我来说非常合适,因为我可以控制我拥有的客户,因此我可以立即强制使用websockets,我相信这是原始问题所要求的.我希望这可以帮助那些人......
归档时间: |
|
查看次数: |
36417 次 |
最近记录: |