WebSocket Draft 76握手混淆

本文关键字:Draft WebSocket | 更新日期: 2023-09-27 18:03:40

我想我可能是第一百万个有问题的人;我希望有人能帮我解决这个问题!

不管怎样;我有这个c#服务器,我试图用WebSockets很好地运行,遗憾的是我无法得到该死的东西来建立连接!扯我头发也没用。

    internal class Request
    {
        private delegate void _create_request(Request request);
        private Request(_create_request create_function)
        {
            Headers = new Dictionary<string, string>();
            Headers["Upgrade"] = null;
            Headers["Connection"] = null;
            Headers["Host"] = null;
            Headers["Origin"] = null;
            Headers["Sec-WebSocket-Key1"] = null;
            Headers["Sec-WebSocket-Key2"] = null;
            Headers["Sec-WebSocket-Protocol"] = null;
            Success = false;
            Secure = false;
            Method = "GET";
            Code = new byte[8];
            create_function(this);
        }
        /// <summary>
        /// the code value is the last 8 bytes of the packet
        /// </summary>
        public byte[] Code { get; internal set; }
        /// <summary>
        /// the resource is the directory being associated with optional extension
        /// eg: ws://localhost:90/[resource]
        /// </summary>
        public string Resource { get; internal set; }
        /// <summary>
        /// the resource is the directory being associated with optional extensions
        /// </summary>
        public bool Success { get; internal set; }
        /// <summary>
        /// this value can either be "GET"
        /// </summary>
        public string Method { get; internal set; }
        /// <summary>
        /// is this connection using a wss:// or ws:// configuration
        /// </summary>
        public bool Secure { get; internal set; }
        /// <summary>
        /// these values contain information about our connection
        /// </summary>
        public Dictionary<string, string> Headers { get; internal set; }
        /// <summary>
        /// this value will give you the responce buffer to pass to the WebSocket server
        /// </summary>
        public byte[] Response
        {
            get
            {
                if (!Success)
                {
                    return null;
                }
                byte[] key_value1 = _get_key_value(Headers["Sec-WebSocket-Key1"]);
                byte[] key_value2 = _get_key_value(Headers["Sec-WebSocket-Key2"]);
                byte[] concatenatedKeys = new byte[16];
                Array.Copy(key_value1, 0, concatenatedKeys, 0, 4);
                Array.Copy(key_value2, 0, concatenatedKeys, 4, 4);
                Array.Copy(Code, 0, concatenatedKeys, 8, 8);
                // MD5 Hash
                System.Security.Cryptography.MD5 MD5Service = System.Security.Cryptography.MD5.Create();
                byte[] challenge_buffer = MD5Service.ComputeHash(concatenatedKeys);
                string response = "HTTP/1.1 101 WebSocket Protocol Handshake'r'n";
                response += "Upgrade: WebSocket'r'n";
                response += "Connection: Upgrade'r'n";
                response += "Sec-WebSocket-Origin: " + Headers["Origin"] + "'r'n";
                string location = ((Secure) ? "wss://" : "ws://") + Headers["Host"] + "/" + Resource;
                response += "Sec-WebSocket-Location: " + location + "'r'n";
                string protocol = Headers["Sec-WebSocket-Protocol"];
                if (Headers["Sec-WebSocket-Protocol"] == null)
                {
                    protocol = "*";
                }
                response += "Sec-WebSocket-Protocol: " + protocol.Trim(' ') + "'r'n";
                response += "'r'n";
                byte[] response_buffer = new byte[response.Length + 16];
                Array.Copy(Encoding.ASCII.GetBytes(response), 0, response_buffer, 0, response.Length);
                Array.Copy(challenge_buffer, 0, response_buffer, response.Length, 16);
                return response_buffer;
            }
        }
        internal byte[] _get_key_value(string key)
        {
            byte[] value = new byte[4];
            ulong r = 0;
            ulong s = 0;
            for (int i = 0; i < key.Length; ++i)
            {
                if (key[i] > '0' && key[i] < '9')
                {
                    r = r * 10 + key[i] - '0';
                }
                else if (key[i] == ' ')
                {
                    s++;
                }
            }
            value = BitConverter.GetBytes(r / s);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(value);
            }
            return value;
        }
        /// <summary>
        /// this function will instantiate a new request object, from request data
        /// </summary>
        /// <param name="data">the request data</param>
        /// <returns></returns>
        internal static Request Instantiate(byte[] data)
        {
            string sdata = Encoding.ASCII.GetString(data);
            return new Request(delegate(Request request)
            {
                string _regex_descriptor = @"^([^ ]+)'s'/([^ ]+)'sHTTP/1.1";
                string _regex_header = @"'n([^:]+):'s([^'r'n]+)";
                string _regex_secure = "^ws([^:]+)?:''/''/";
                Match match_descriptor = Regex.Match(sdata, _regex_descriptor);
                MatchCollection match_headers = Regex.Matches(sdata, _regex_header);
                if (match_descriptor.Success)
                {
                    request.Method = match_descriptor.Groups[1].Value;
                    request.Resource = match_descriptor.Groups[2].Value;
                    //Console.WriteLine("Method = " + request.Method);
                    //Console.WriteLine("Resource = " + request.Resource);
                }
                else return;
                if (match_headers.Count > 0)
                {
                    foreach (Match match in match_headers)
                    {
                        if (match.Success)
                        {
                            if (match.Groups[1].Value == "Host")
                            {
                                Match match_secure = Regex.Match(match.Groups[2].Value, _regex_secure);
                                if (match_secure.Success)
                                {
                                    request.Secure = (match_secure.Groups[1].Value == "s");
                                }
                            }
                            request.Headers[match.Groups[1].Value] = match.Groups[2].Value;
                            //Console.WriteLine("Header['"" + match.Groups[1].Value + "'"] = " + match.Groups[2].Value);
                        }
                    }
                }
                else return;
                Array.Copy(data, data.Length - 8, request.Code, 0, 8);
                request.Success = true;
            });
        }
    }

基本上,如果你调用myRequest = Request.Instantiate(byte[] handshake_packet);然后调用myRequest.Response生成响应缓冲区;如果有人发现我的方法有任何问题,请告诉我;因为在我解决这个问题之前,我真的睡不着。

WebSocket Draft 76握手混淆

您似乎没有将09作为一个数字。其次,_get_key_value返回byte[8]而不是byte[4]

因此,首先在_get_key_value中修改以下内容(注意>=<=):
if (key[i] >= '0' && key[i] <= '9')

并在同一函数中更改以下内容(注意转换为int,因为它始终是整数,整数有4个字节,这是正确的):

value = BitConverter.GetBytes((int)(r / s));

因为规范规定:

…|Sec- WebSocket-Key1|字段,表示为大端32位,处理|Sec- websocket - key2 |字段得到的数字,再次表示为大端32位,…

现在我可以从维基百科文章中的示例请求中获得正确的响应。