C#WebSocket创建蒙版框架

时间:2017-07-10 15:04:45

标签: c# websocket

我试图在C#中自己创建一个WebSocket协议,以了解它是如何工作的。

我做了服务器和客户端。

我能够握手,发送和接收消息(客户端和服务器都运行良好)但我在向客户端发送屏蔽消息时遇到问题。

以下是我使用NetworkStream.Write创建要发送的框架的代码:

private byte[] EncodeOutgoingMessage(string text, bool masked = false)
{
    /* this is how and header should be made:
     *   - first byte  -> FIN + RSV1 + RSV2 + RSV3 + OPCODE
     *   - second byte -> MASK + payload length (only 7 bits)
     *   - third, fourth, fifth and sixth bytes -> (optional) XOR encoding key bytes
     *   - following bytes -> the encoded (if a key has been used) payload
     *
     *   FIN    [1 bit]      -> 1 if the whole message is contained in this frame, 0 otherwise
     *   RSVs   [1 bit each] -> MUST be 0 unless an extension is negotiated that defines meanings for non-zero values
     *   OPCODE [4 bits]     -> defines the interpretation of the carried payload
     *
     *   MASK           [1 bit]  -> 1 if the message is XOR masked with a key, 0 otherwise
     *   payload length [7 bits] -> can be max 1111111 (127 dec), so, the payload cannot be more than 127 bytes per frame
     *
     * valid OPCODES:
     *   - 0000 [0]             -> continuation frame
     *   - 0001 [1]             -> text frame
     *   - 0010 [2]             -> binary frame
     *   - 0011 [3] to 0111 [7] -> reserved for further non-control frames
     *   - 1000 [8]             -> connection close
     *   - 1001 [9]             -> ping
     *   - 1010 [A]             -> pong
     *   - 1011 [B] to 1111 [F] -> reserved for further control frames
     */
    // in our case the first byte will be 10000001 (129 dec = 81 hex).
    // the length is going to be (masked)1 << 7 (OR) 0 + payload length.
    byte[] header = new byte[] { 0x81, (byte)((masked ? 0x1 << 7 : 0x0) + text.Length) };
    // by default the mask array is empty...
    byte[] maskKey = new byte[4];
    if(masked)
    {
        // but if needed, let's create it properly.
        Random rd = new Random();
        rd.NextBytes(maskKey);
    }
    // let's get the bytes of the message to send.
    byte[] payload = Encoding.UTF8.GetBytes(text);
    // this is going to be the whole frame to send.
    byte[] frame = new byte[header.Length + (masked ? maskKey.Length : 0) + payload.Length];
    // add the header.
    Array.Copy(header, frame, header.Length);
    // add the mask if necessary.
    if(maskKey.Length > 0)
    {
        Array.Copy(maskKey, 0, frame, header.Length, maskKey.Length);
        // let's encode the payload using the mask.
        for(int i = 0; i < payload.Length; i++)
        {
            payload[i] = (byte)(payload[i] ^ maskKey[i % maskKey.Length]);
        }
    }
    // add the payload.
    Array.Copy(payload, 0, frame, header.Length + (masked ? maskKey.Length : 0), payload.Length);
    return frame;
}

所以...使用

byte[] answer = EncodeOutgoingMessage("Ciao !!  :)");
stream.Write(answer, 0, answer.Length);

效果很好,但

byte[] answer = EncodeOutgoingMessage("Ciao !!  :)", true);
stream.Write(answer, 0, answer.Length);

将导致客户端收到错误的字符串。

请有人发现我做错了吗?

1 个答案:

答案 0 :(得分:0)

我不是 100% 确定,但我发现了这个:Writing WebSocket servers

<块引用>

向客户端发回帧时,不要屏蔽它,也不要设置屏蔽位。

也许有帮助...