Temos um jogo para celular usando o websocket para conexões. O servidor é um aplicativo Node.js. usando a biblioteca uWebSockets.js e o cliente é um aplicativo Unity usando a biblioteca Websocket-Sharp . Ambos jogam bem juntos e não encontramos um problema com eles.
Recentemente, queríamos ativar a compactação do websocket . Ambas as bibliotecas declararam que suportam a extensão de compactação por mensagem, mas parece que há algo incompatível com elas. Porque quando configuramos para usar a compactação, a conexão do websocket fecha imediatamente no handshake.
Também testamos o cliente com a biblioteca ws e é fornecido um exemplo de compactação com o mesmo resultado. Tentamos mexer nas opções de compactação ws e descobrimos que, quando comentamos a opção serverMaxWindowBits (o padrão é o valor negociado), a conexão pode ser estabelecida e o envio e recebimento de mensagens funcionam sem problemas. Também perguntamos sobre o controle do serverMaxWindowBits no uWebsockets.
A última coisa que tentamos foi conectar um servidor uWS mínimo e um cliente afiado ao websocket. Aqui está o código para o servidor:
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);
}
});
Aqui está o código do cliente:
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);
}
}
}
}
Quando executamos o servidor e o cliente, o cliente emite o seguinte erro:
Erro | WebSocket.checkHandshakeResponse | O servidor não enviou de volta 'server_no_context_takeover'. Fatal | WebSocket.doHandshake | Inclui um cabeçalho Sec-WebSocket-Extensions inválido.
Parecia que o cliente esperava o cabeçalho server_no_context_takeover e não recebeu um. Revisamos uWebsockets fonte (parte C ++ do módulo uWebsockets.js) e encontrou uma condição comentou para o envio de cabeçalho de volta server_no_context_takeover. Por isso, descomentamos a condição e construímos o uWebsockets.js e testamos novamente para encontrar o seguinte erro no cliente:
WebSocketSharp.WebSocketException: o cabeçalho de um quadro não pode ser lido do fluxo.
Alguma sugestão para que essas duas bibliotecas funcionem juntas?
Respostas:
Atualização: com base na minha leitura do código
uWebSockets.js
, alterações precisariam ser feitas para ativar todos os parâmetroswebsocket-sharp
necessários para ativar a compactação. No Vertx, um servidor Java de alto desempenho, as seguintes configurações funcionam com o Unity compatívelwebsocket-sharp
para compactação:Anteriormente:
O erro é real,
websocket-sharp
apenas suportapermessage-deflate
, useDEDICATED_COMPRESSOR
(compression: 2
).fonte
WebSocket.cs
rejeição de cabeçalho?DEDICATED_COMPRESSOR
realmente deve funcionar!