javascript - rooms - socket.io php
Socket.io 1.x: ¿solo usa WebSockets? (4)
Estamos desarrollando una aplicación web que se ejecutará solo en los navegadores modernos (IE10 +) por diferentes motivos.
Una de las características que implementamos es Socket.io 1.x. Sin embargo, de forma predeterminada, el cliente Socket.io intenta admitir navegadores antiguos, por lo que inicia una conexión con un sondeo largo y luego lo actualiza a WebSockets. Esto es una pérdida de tiempo y recursos, dado que sabemos con certeza que el navegador es compatible con WS.
He buscado y solo puedo encontrar esta página wiki que, sin embargo, trata sobre Socket.io 0.9.
Finalmente, encontré la documentación para engine.io-client (en la que Socket.io-client se basa en la rama 1.x). Este es el código que escribí y parece estar funcionando. Sin embargo, me gustaría saber si es correcto o si estoy haciendo algo mal:
io.connect(''https://...'', {
upgrade: false,
transports: [''websocket'']
})
Extrañamente, simplemente establecer la propiedad de transports
en una matriz con websockets
no era suficiente; También tuve que deshabilitar la upgrade
. ¿Es esto correcto?
Actualizar
Hice algunos descubrimientos nuevos.
Con los transports
configurados en [''websocket'']
solamente, no importa si su upgrade
está habilitada o no. ¿Eso es normal?
Estoy publicando esa respuesta porque la respuesta aceptada no es correcta: confunde la actualización de Socket.IO de AJAX de larga duración a WebSocket con la solicitud de "Conexión: Actualización" del protocolo WSS. El problema no es que la conexión WebSocket se inicie como HTTP y se actualice a WebSocket, ¿cómo podría ser? - pero ese Socket.IO comienza con una larga conexión AJAX incluso en navegadores compatibles con WebSocket, y solo la actualiza más tarde después de intercambiar algo de tráfico. Es muy fácil de ver en las herramientas de desarrollador de Firefox o Chrome.
El autor de la pregunta es correcto en sus observaciones. La "actualización" en Socket.IO no se refiere a la actualización del protocolo HTTP a WSS, como suele malinterpretarse, sino a la actualización de la conexión Socket.IO desde la conexión AJAX de larga duración a WebSocket. Si ya comienza con WebSocket (que no es el predeterminado), actualizar falsa no tiene ningún efecto porque no necesita actualizar. Si comienza con el sondeo y deshabilita la actualización, se mantiene así y no se actualiza a WebSocket.
Vea las respuestas de Arnold y Nick Steele si quiere evitar comenzar con largas encuestas. Explicaré lo que está pasando con más detalle.
Esto es lo que observé en mis experimentos con aplicaciones simples WebSocket y Socket.IO:
WebSocket
2 solicitudes, 1.50 KB, 0.05 s
De esas 2 solicitudes:
- La página HTML en sí
- actualización de conexión a WebSocket
(La solicitud de actualización de conexión está visible en las herramientas de desarrollador con una respuesta de 101 Protocolos de conmutación).
Socket.IO
6 solicitudes, 181.56 KB, 0.25 s
De esas 6 solicitudes:
- la página HTML en sí
- JavaScript de Socket.IO (180 kilobytes)
- primer pedido largo AJAX de sondeo
- segunda solicitud larga de AJAX de sondeo
- tercera solicitud AJAX de larga encuesta
- actualización de conexión a WebSocket
Detalles
Resultados de WebSocket que obtuve en localhost:
Resultados de Socket.IO que obtuve en localhost:
Pruébate
Publiqué el código en npm y en GitHub , puede ejecutarlo usted mismo:
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
y sigue las inscripciones Para desinstalar:
# Uninstall:
npm rm -g websocket-vs-socket.io
Vea esta respuesta para más información.
Hay dos tipos de "actualizaciones" que suceden con socket.io. Primero (en socket.io 1.0+), socket.io inicia todas las conexiones con una solicitud de sondeo http y, de hecho, puede intercambiar algunos datos iniciales con solo una solicitud http. Luego, en algún momento después de eso, tratará de iniciar realmente una conexión webSocket. La conexión webSocket se realiza mediante el envío de un tipo particular de solicitud http que especifica una upgrade: websocket
encabezado upgrade: websocket
y el servidor puede entonces responder adecuadamente si admite websocket o no. Si el servidor acepta la actualización, esa conexión http particular se "actualiza" al protocolo webSocket. En ese momento, el cliente sabe que webSocket es compatible y deja de usar las solicitudes http de sondeo, completando así su upgrade
a webSocket.
Puede evitar la encuesta http inicial por completo al hacer esto en el cliente:
var socket = io({transports: [''websocket''], upgrade: false});
Esto evitará las conexiones de votación de sus propios clientes que cooperan. Si desea evitar que los clientes utilicen sondeos, puede agregar esto al servidor:
io.set(''transports'', [''websocket'']);
Pero, si configura esto en el servidor, los clientes de socket.io que se conectan inicialmente con el sondeo http no funcionarán en absoluto. Por lo tanto, esto solo debería coincidir con las configuraciones correctas en el cliente, de modo que el cliente nunca comience con la votación.
Esto le indicará a ambos extremos que solo desea usar webSockets y socket.io omitirá la encuesta HTTP adicional al principio. Una advertencia justa, hacer esto requiere soporte webSocket por lo que esto descarta la compatibilidad con versiones anteriores de IE que aún no soportaban webSocket. Si desea mantener la compatibilidad, simplemente deje que socket.io lo haga con un par de solicitudes http inicialmente.
Aquí hay más información sobre la actualización del protocolo de http a webSocket.
El protocolo webSockets inicia CADA webSocket con una conexión HTTP. Esa es la forma en que funcionan todos los WebSockets. Esa conexión HTTP contiene algunos encabezados que indican que al navegador le gustaría "actualizar" al protocolo webSockets. Si el servidor admite ese protocolo, responde diciéndole al cliente que se actualizará al protocolo webSocket y que ese mismo socket cambia del protocolo HTTP al protocolo webSocket. Así es como una conexión webSocket está diseñada para funcionar. Por lo tanto, el hecho de que vea su conexión webSocket comenzando con una conexión HTTP es 100% normal.
Puede configurar socket.io para NUNCA usar un sondeo largo si eso lo hace sentir mejor, pero esto no cambiará el hecho de que la conexión webSocket todavía comenzará con una conexión HTTP que luego se actualizará al protocolo webSocket y no mejorará la eficiencia de operación en navegadores modernos que admiten webSockets. Sin embargo, hará que su conexión no funcione en navegadores más antiguos.
Para decirle a Socket.IO que use WebSocket solo en lugar de unas pocas solicitudes XHR primero, simplemente agregue esto al servidor de Nodo:
io.set(''transports'', [''websocket'']);
Y en el cliente agrega esto:
var socket = io({transports: [''websocket'']});
Esto le dice a Socket.IO que solo use el protocolo WebSocket y nada más; es más limpio, más rápido y utiliza un poco menos de recursos en los lados del cliente y del servidor.
Ahora solo verá una sola conexión WebSocket en su lista de solicitudes de red, solo tenga en cuenta que IE9 y anteriores no pueden usar WebSocket.
Pensé que debería agregar a la respuesta aceptada anteriormente, como si alguien quisiera eliminar el transporte XHR Polling e iniciar websockets de inmediato. El siguiente código es solo para dar una idea de la implementación:
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);
});
});
Después de configurar el servidor, verá esto:
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
Si no fuerza el transporte, verá "sondeo" en lugar de websocket. Sin embargo, esto no ocurre solo en el lado del cliente, el servidor también debe configurarse:
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.
Peligro
Si el cliente no admite el protocolo websocket, no se establecerá una conexión y el cliente informará un xhr poll error
.
Esto funciona perfectamente para mí porque puedo controlar a los clientes que tengo, así que tengo el lujo de forzar los websockets de inmediato, lo cual creo que es lo que la pregunta original está haciendo. Espero que esto ayude a alguien por ahí ...