Nous avons un jeu mobile utilisant websocket pour les connexions. Le serveur est une application Node.js utilisant bibliothèque uWebSockets.js et le client est une application Unity utilisant la bibliothèque Websocket-Sharp . Ils jouent tous les deux bien ensemble et nous n'avons rencontré aucun problème avec eux.
Récemment, nous voulions activer la compression Websocket . Les deux bibliothèques ont déclaré qu'elles prennent en charge l'extension de compression par message, mais il semble qu'il y ait quelque chose d'incompatible avec elles. Parce que lorsque nous configurons pour utiliser la compression, la connexion websocket se ferme immédiatement lors de la prise de contact.
Nous avons également testé le client avec ws bibliothèque et il est fourni un exemple de compression avec le même résultat. Nous avons essayé de bricoler les options de compression ws et avons constaté que lorsque nous commentions l'option serverMaxWindowBits (par défaut la valeur négociée), la connexion pouvait être établie et l'envoi et la réception de messages fonctionnaient sans problème. Nous avons également demandé comment contrôler les serverMaxWindowBits dans uWebsockets.
La dernière chose que nous avons essayée a été de connecter un serveur uWS minimal et un client websocket-sharp. Voici le code du serveur:
const uWS = require('uWebSockets.js');
const port = 5001;
const app = uWS.App({
}).ws('/*', {
/* Options */
compression: 1, // Setting shared compression method
maxPayloadLength: 4 * 1024,
idleTimeout: 1000,
/* Handlers */
open: (ws, req) => {
console.log('A WebSocket connected via URL: ' + req.getUrl() + '!');
},
message: (ws, message, isBinary) => {
/* echo every message received */
let ok = ws.send(message, isBinary);
},
drain: (ws) => {
console.log('WebSocket backpressure: ' + ws.getBufferedAmount());
},
close: (ws, code, message) => {
console.log('WebSocket closed');
}
}).any('/*', (res, req) => {
res.end('Nothing to see here!');
}).listen(port, (token) => {
if (token) {
console.log('Listening to port ' + port);
} else {
console.log('Failed to listen to port ' + port);
}
});
Voici le code client:
using System;
using WebSocketSharp;
namespace Example
{
public class Program
{
public static void Main (string[] args)
{
using (var ws = new WebSocket ("ws://localhost:5001")) {
ws.OnMessage += (sender, e) =>
Console.WriteLine ("server says: " + e.Data);
ws.Compression = CompressionMethod.Deflate; // Turning on compression
ws.Connect ();
ws.Send ("{\"comm\":\"example\"}");
Console.ReadKey (true);
}
}
}
}
Lorsque nous avons exécuté le serveur et le client, le client émet l'erreur suivante:
Erreur | WebSocket.checkHandshakeResponse | Le serveur n'a pas renvoyé 'server_no_context_takeover'. Fatal | WebSocket.doHandshake | Inclut un en-tête Sec-WebSocket-Extensions non valide.
Il semblait que le client attendait l'en-tête server_no_context_takeover et n'en avait pas reçu. Nous avons examiné la source uWebsockets (partie C ++ du module uWebsockets.js) et trouvé une condition commentée pour renvoyer l'en-tête server_no_context_takeover. Nous avons donc décommenté la condition et créé uWebsockets.js et testé à nouveau pour rencontrer l'erreur suivante dans le client:
WebSocketSharp.WebSocketException: l'en-tête d'une trame ne peut pas être lu à partir du flux.
Avez-vous des suggestions pour faire fonctionner ces deux bibliothèques ensemble?
Réponses:
Mise à jour: Sur la base de ma lecture du code dans
uWebSockets.js
, des modifications devraient être apportées pour activer tous les paramètreswebsocket-sharp
requis pour activer la compression. Dans Vertx, un serveur Java hautes performances, les paramètres suivants fonctionnent avec la compatibilité Unitywebsocket-sharp
pour la compression:Précédemment:
L'erreur est réelle,
websocket-sharp
ne prend en charge quepermessage-deflate
, utilisez plutôtDEDICATED_COMPRESSOR
(compression: 2
).la source
WebSocket.cs
rejet d'en-tête de?DEDICATED_COMPRESSOR
devrait vraiment fonctionner!