@legacy_js

Браузеры реализуют протокол websoket по разном?

Написал простенький вебсокет сервер взяв от сюда некоторые методы.
Мой код
class WS
    {
        private readonly string GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        private readonly string ip;
        private readonly int port;
        byte[] Segment { get; } = new byte[512];
        public Socket socket { get; set; }

        public WS(int port, string ip)
        {
            this.port = port;
            this.ip = ip;
            IPAddress[] ipAddress = Dns.GetHostAddresses(this.ip);
            IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress[0], this.port);
            this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this.Bind(ipLocalEndPoint);
            this.Listen();
        }
        private byte[] GetHandshake(string key)
        {
            string acceptSHA1 = key + GUID;
            byte[] encodingBytes = Encoding.ASCII.GetBytes(acceptSHA1);
            byte[] hash = SHA1.HashData(encodingBytes);
            var hashString = Convert.ToBase64String(hash);

            byte[] msg = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols\r\n" +
                "Upgrade: websocket\r\n" +
                "Connection: Upgrade\r\n" +
                "Sec-WebSocket-Accept: " + hashString +
                "\r\n\r\n");
            Console.WriteLine(Encoding.UTF8.GetString(msg));
            return msg;
        }

        public async Task<int> GetKeyWS(Socket acceptData)
        {
            await acceptData.ReceiveAsync(this.Segment);

            HttpInfo headersKey = new HttpInfo(this.Segment);

            byte[] buffer = GetHandshake(headersKey.GetHeaderValue("Sec-WebSocket-Key"));
            await acceptData.SendAsync(buffer);

            byte[] bytes = new byte[65536];

            while (true)
            {
                
                if (bytes[0] == 136)
                {

                    for (int i = 0; i < 6; ++i)
                    {
                        Console.WriteLine(bytes[i]);
                    }

                    return 0;
                }
                else
                {
                    await acceptData.ReceiveAsync(bytes);
                    Console.WriteLine(acceptData.RemoteEndPoint);
                    int payload = bytes[1] & 127;

                    int payloadLength = (bytes[1] & 127) < 126 ? bytes[1] & 127 : BitConverter.ToInt16(new byte[] { bytes[3], bytes[2] }, 0);

                    byte[] dataBuffer;

                    byte[] slice = new byte[4];

                    int offset = 0;

                    if (payloadLength <= 125)
                    {
                        slice = bytes[2..^5];
                        offset = 2;
                    }

                    int payload_first_byte = offset + 4;
                    byte[] decode = new byte[payloadLength];

                    for (int i = 0; i < payload; ++i, ++payload_first_byte)
                    {
                        decode[i] = (byte)(bytes[payload_first_byte] ^ slice[i % 4]);

                    }
                    dataBuffer = new byte[] { 129, Convert.ToByte(payload) };
                    byte[] arraySend = new byte[dataBuffer.Length + decode.Length];

                    Array.Copy(dataBuffer, 0, arraySend, 0, dataBuffer.Length);
                    Array.Copy(decode, 0, arraySend, 2, decode.Length);

                    await acceptData.SendAsync(arraySend);
                }
            }
        }
        private void Bind(IPEndPoint ep)
        {
            this.socket.Bind(ep);
        }
        private void Listen()
        {
            this.socket.Listen();
        }
    }
    internal class Program
    {
        static async Task<int> Main()
        {
            WS ws = new(7878, "192.168.0.2");

            try
            {
                while (true)
                {
                    var acceptAsync = await ws.socket.AcceptAsync();

                    new Thread(async () => await ws.GetKeyWS(acceptAsync)).Start();
                }
            }
            catch (Exception ex) 
            { 
                Console.WriteLine(ex.Message);
                return 0;
            }

        }
    }

Клиент
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<form name="publish">
    <input type="text" name="message" onsubmit="return false;">
    <input type="submit" value="Отправить" onsubmit="return false;">
</form>

<div id="messages"></div>
<script>
    let manualPongIntervalId;
    const ws =  new WebSocket("ws://192.168.0.2:7878");
    const serverPingInterval = 30000;
    let socket = null;
    ws.onopen = () => {
        console.log('OPEN')
    }

    document.forms.publish.onsubmit = function(e) {
        e.preventDefault();
        let outgoingMessage = this.message.value;
        ws.send(outgoingMessage);
        return false
    }

    ws.onmessage = function(event) {
        let message = event.data;

        let messageElem = document.createElement('div');

        messageElem.textContent = message;

        document.getElementById('messages').prepend(messageElem);
    };
    
    ws.onclose = (event) => {

    };

    ws.onerror = function(error) {
        console.log(`[error] ${error.message}`);
    };
</script>
</body>
</html>

GetFrameData
public static SFrameMaskData GetFrameData(byte[] Data) 
        {
            int opcode = Data[0] & 127;
            int l = Data[1] & 127;
            // If the length of the message is in the 2 first indexes
            if (l <= 125)
            {
                int dataLength = (Data[1] & 127);

                Console.WriteLine("opcode - " + opcode);

                return new SFrameMaskData(dataLength, 2, dataLength + 6, (EOpcodeType)opcode);
            }

            // If the length of the message is in the following two indexes
            if (l == 126)
            {
                // Combine the bytes to get the length
                int dataLength = BitConverter.ToInt16(new byte[] { Data[3], Data[2] }, 0);
                return new SFrameMaskData(dataLength, 4, dataLength + 8, (EOpcodeType)opcode);
            }

            // If the data length is in the following 8 indexes
            if (l == 127)
            {
                // Get the following 8 bytes to combine to get the data 
                byte[] combine = new byte[8];
                for (int i = 0; i < 8; i++) combine[i] = Data[i + 2];

                // Combine the bytes to get the length
                //int dataLength = (int)BitConverter.ToInt64(new byte[] { Data[9], Data[8], Data[7], Data[6], Data[5], Data[4], Data[3], Data[2] }, 0);
                int dataLength = (int)BitConverter.ToInt64(combine, 0);
                return new SFrameMaskData(dataLength, 10, dataLength + 14, (EOpcodeType)opcode);
            }

            // error
            return new SFrameMaskData(0, 0, 0, 0);
        }

В хроме все хорошо, при открытии соединения я не чего не получаю, при закрытии соединения получаю
byte[0] - 136
opcode - 8
lenght - 2
Frame - ClosedConnection

Но при открытии в других браузерах, я сразу же получаю не понятные сообщения.
В opera при открытии
spoiler
,oezUbow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_bow_b

byte[0] - 110
opcode - 110
lenght - 100
Frame - 110

При закрытии соединения
byte[0] - 136
opcode - 8
lenght - 2
Frame - ClosedConnection
byte[0] - 110
opcode - 110
lenght - 100
Frame - 110

В яндексе такое сообщение при открытии
spoiler
ocyybitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbitsbit

byte[0] - 119
opcode - 119
lenght - 95
Frame - 119

При закрытии соединения
byte[0] - 136
opcode - 8
lenght - 2
Frame - ClosedConnection
byte[0] - 119
opcode - 119
lenght - 95
Frame - 119

Не могу понять, или это я что то не так делаю, или суть вопроса?
  • Вопрос задан
  • 83 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы