C# receives garbled websocket messages sent from JS

C# starts a Socket service and connects with js. When C# parses the js message, a Chinese garbled problem occurs. Just upload the code:

        private static SocketHelper _instance;
        public static SocketHelper Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new SocketHelper();
                return _instance;
            }
        }

        Socket clientSocket;
        Socket _clientSocket;        
        Thread listenThread;
        int _port = 0;

        public SocketHelper()
        {
            
        }

        public void InitSocket(int port)
        {
            _port = port;
            listenThread = new Thread(websocketListen);
            listenThread.IsBackground = true;
            listenThread.Start();
        }

        private void websocketListen()
        {
            IPAddress ip = IPAddress.Parse("0.0.0.0");
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Bind(new IPEndPoint(ip, _port));  //绑定IP地址:端口  
            clientSocket.Listen(10);    //设定最多10个排队连接请求  
            _log.Info($"socket服务 启动监听成功,地址:{clientSocket.LocalEndPoint.ToString()}");

            // 监听多个客户端连接
            while (true)
            {
                _clientSocket = clientSocket.Accept();
                _log.Info($"socket服务 收到客户端连接,地址:{_clientSocket.RemoteEndPoint}");
                Console.WriteLine($"收到客户端连接,地址:{_clientSocket.RemoteEndPoint}");

                //接收客户端发来的HTTP-Header消息
                byte[] bytes = new byte[1024];
                int len = _clientSocket.Receive(bytes);
                string strMessage = Encoding.UTF8.GetString(bytes, 0, len);
                Console.WriteLine(strMessage);

                //获取Sec-WebSocket-Key,为握手做准备
                string[] strings = strMessage.Split('\n');
                string strSecWebSocketKey = "";
                foreach (var item in strings)
                {
                    string[] strings1 = item.Split(':');
                    if (strings1[0] == "Sec-WebSocket-Key")
                    {
                        strSecWebSocketKey = strings1[1].Trim();
                    }
                }

                //生成服务端Sec-WebSocket-Accept,迎合客户端的握手请求
                byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(strSecWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
                string secKey = Convert.ToBase64String(secKeyBytes);

                // 发送给客户端完成握手(会触发Websocket的open()回调函数),针对websocket必须使用以下header
                string strHeader = "";
                strHeader += "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
                strHeader += "Upgrade: websocket" + Environment.NewLine;
                strHeader += "Connection: Upgrade" + Environment.NewLine;
                strHeader += "Sec-WebSocket-Accept: " + secKey + Environment.NewLine + Environment.NewLine;
                _clientSocket.Send(Encoding.UTF8.GetBytes(strHeader));

                //string remoteFileUrl = null;
                bool clientClose = false;
                // 循环接收websocket发来的消息实现双方交流
                while (!clientClose)
                {
                    //接收客户端发来的消息
                    byte[] bytes2 = new byte[1024];
                    int len2 = _clientSocket.Receive(bytes2);
                    string strMessage2 = AnalyticData(bytes2, len2);
                    try
                    {
                        if (len2 == 0)
                            break;
                        var msgData = JsonConvert.DeserializeObject<MsgData>(strMessage2);
                        if (msgData != null)
                        {
                            Messenger.Default.Send(msgData.type, "SocketMsg");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("处理web发来的socket消息异常:" + ex.Message);
                    }
                }
            }
        }

        public void SendMessage(string msg)
        {
            if (msg == string.Empty)
                return;
            try
            {
                _log.Info($"socket服务 即将发送socket消息,内容:{msg}");
                _clientSocket?.Send(PackData(msg));
            }
            catch (Exception ex)
            {
                _log.Error($"socket服务 发送消息异常,发送内容:{msg},异常信息:{ex.Message}");
            }
        }
      
        /// <summary>
        /// 解析客户端数据包,防止乱码
        /// </summary>
        /// <param name="recBytes">服务器接收的数据包</param>
        /// <param name="recByteLength">有效数据长度</param>
        /// <returns></returns>
        private static string AnalyticData(byte[] recBytes, int recByteLength)
        {
            if (recByteLength < 2) { return string.Empty; }
            bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧  
            if (!fin)
            {
                return string.Empty;// 超过一帧暂不处理 
            }
            bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码  
            if (!mask_flag)
            {
                return string.Empty;// 不包含掩码的暂不处理
            }
            int payload_len = recBytes[1] & 0x7F; // 数据长度  
            byte[] masks = new byte[4];
            byte[] payload_data;
            if (payload_len == 126)
            {
                Array.Copy(recBytes, 4, masks, 0, 4);
                payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, 8, payload_data, 0, payload_len);
            }
            else if (payload_len == 127)
            {
                Array.Copy(recBytes, 10, masks, 0, 4);
                byte[] uInt64Bytes = new byte[8];
                for (int i = 0; i < 8; i++)
                {
                    uInt64Bytes[i] = recBytes[9 - i];
                }
                UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
                payload_data = new byte[len];
                for (UInt64 i = 0; i < len; i++)
                {
                    payload_data[i] = recBytes[i + 14];
                }
            }
            else
            {
                Array.Copy(recBytes, 2, masks, 0, 4);
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, 6, payload_data, 0, payload_len);
            }
            for (var i = 0; i < payload_len; i++)
            {
                payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
            }
            return Encoding.UTF8.GetString(payload_data);
        }

        /// <summary>
        /// 打包服务器数据,防止乱码
        /// </summary>
        /// <param name="message">数据</param>
        /// <returns>数据包</returns>
        private static byte[] PackData(string message)
        {
            byte[] contentBytes = null;
            byte[] temp = Encoding.UTF8.GetBytes(message);
            if (temp.Length < 126)
            {
                contentBytes = new byte[temp.Length + 2];
                contentBytes[0] = 0x81;
                contentBytes[1] = (byte)temp.Length;
                Array.Copy(temp, 0, contentBytes, 2, temp.Length);
            }
            else if (temp.Length < 0xFFFF)
            {
                contentBytes = new byte[temp.Length + 4];
                contentBytes[0] = 0x81;
                contentBytes[1] = 126;
                contentBytes[2] = (byte)(temp.Length & 0xFF);
                contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
                Array.Copy(temp, 0, contentBytes, 4, temp.Length);
            }
            else
            {
                // 暂不处理超长内容  
            }
            return contentBytes;
        }

Guess you like

Origin blog.csdn.net/u013543846/article/details/130708768