Мне нужно реализовать простой WebSocket сервер. Если фрагментация не используется на клиенте, данные доходят верно, но в обратном случае приходит много пакетов в том числе с неопределенными опкодами:
{ opcode: 1, length: 65522, last: 0 }
{ opcode: 7, length: 65472, last: 128 }
{ opcode: 0, length: 65522, last: 0 }
{ opcode: 3, length: 65530, last: 0 }
{ opcode: 14, length: 65530, last: 128 }
{ opcode: 3, length: 65530, last: 128 }
{ opcode: 15, length: 65530, last: 0 }
{ opcode: 2, length: 65530, last: 0 }
{ opcode: 7, length: 65530, last: 0 }
{ opcode: 10, length: 65530, last: 0 }
{ opcode: 1, length: 65530, last: 128 }
{ opcode: 12, length: 65530, last: 128 }
{ opcode: 15, length: 65530, last: 0 }
{ opcode: 2, length: 65530, last: 0 }
{ opcode: 0, length: 65530, last: 0 }
{ opcode: 13, length: 65530, last: 0 }
{ opcode: 15, length: 65530, last: 128 }
{ opcode: 2, length: 65530, last: 128 }
{ opcode: 0, length: 65528, last: 0 }
{ opcode: 13, length: 65530, last: 0 }
{ opcode: 12, length: 65528, last: 0 }
{ opcode: 1, length: 65530, last: 0 }
{ opcode: 1, length: 65530, last: 128 }
{ opcode: 12, length: 65530, last: 128 }
{ opcode: 12, length: 65530, last: 0 }
{ opcode: 1, length: 65530, last: 0 }
{ opcode: 4, length: 65530, last: 0 }
{ opcode: 9, length: 65530, last: 0 }
{ opcode: 3, length: 65530, last: 128 }
{ opcode: 14, length: 65530, last: 128 }
{ opcode: 13, length: 65530, last: 0 }
{ opcode: 0, length: 65530, last: 0 }
{ opcode: 0, length: 65530, last: 0 }
{ opcode: 13, length: 65530, last: 0 }
{ opcode: 11, length: 65530, last: 128 }
{ opcode: 6, length: 65530, last: 128 }
{ opcode: 14, length: 41016, last: 128 }
server:
'use strict';
const http = require('node:http');
const hash = require('./hash.js');
const handshake = require('./handshake.js');
const parser = require('./parser.js');
const buildAnswer = (message) => {
const buffer = Buffer.alloc(message.length + 2);
buffer[0] = 129;
buffer[1] = message.length;
Buffer.from(message).copy(buffer, 2, 0);
return buffer;
};
const main = () => {
const server = new http.Server();
server.on('upgrade', (request, socket) => {
const { headers } = request;
const { upgrade: protocol } = headers;
if (protocol !== 'websocket') return;
const clientKey = headers['sec-websocket-key'];
const hashed = hash(clientKey);
socket.write(handshake(hashed));
socket.on('data', (chunk) => {
const encoded = chunk.readInt8(1) & 128;
// if (!encoded) return void socket.end();
const opcode = chunk.readUInt8(0) & 15;
const last = chunk.readUInt8(0) & 128;
const mask = parser.getMask(chunk);
const content = parser.getContent(chunk);
const message = Uint8Array.from(content, (elt, i) => elt ^ mask[i % 4]);
const string = String.fromCharCode(...message);
console.log({ opcode, length: string.length, last });
// console.log({ last, opcode });
const answer = buildAnswer('server');
socket.write(answer);
});
socket.on('error', console.log);
});
server.listen(8000, '127.0.0.1');
};
main();
client:
'use strict';
const main = () => {
const ws = new WebSocket('ws://127.0.0.1:8000');
ws.onopen = () => {
console.log('Connected');
ws.send('client'.repeat(400000));
ws.onmessage = (event) => {
console.log(event.data);
};
};
ws.onclose = () => console.log('Closed');
};
main();