Ejemplo n.º 1
0
        /// <summary>
        /// 循环读取消息,禁止重复调用
        /// </summary>
        /// <returns></returns>
        public async Task ReadMessageLoop()
        {
            while (_connected)
            {
                var headBuffer = new byte[ProtocolHeadLength];
                //先读取一次头信息
                await _roomStream.ReadAsync(headBuffer, 0, ProtocolHeadLength);

                //解析头信息
                DanmuHead danmuHead = DanmuHead.BufferToDanmuHead(headBuffer);
                //判断协议
                if (danmuHead.HeaderLength != ProtocolHeadLength)
                {
                    continue;
                }

                //初始化一个放数据的byte数组
                byte[] dataBuffer;
                if (danmuHead.Action == 3)
                {
                    //给服务器发送心跳信息后的回应信息,所带的数据是直播间的观看人数(人气值)
                    dataBuffer = new byte[danmuHead.MessageLength()];
                    await _roomStream.ReadAsync(dataBuffer, 0, danmuHead.MessageLength());

                    var audiences = EndianBitConverter.EndianBitConverter.BigEndian.ToInt32(dataBuffer, 0);
                    _messageHandler.AudiencesHandlerAsync(audiences);
                    continue;
                }

                string  tmpData;
                JObject json = null;
                if (danmuHead.Action == 5 && danmuHead.Version == ProtocolVersion)
                {
                    //有效负载为礼物、弹幕、公告等内容数据
                    //读取数据放入缓冲区
                    dataBuffer = new byte[danmuHead.MessageLength()];
                    await _roomStream.ReadAsync(dataBuffer, 0, danmuHead.MessageLength());

                    //之后把数据放入到内存流
                    string jsonStr;
                    using (var ms = new MemoryStream(dataBuffer, 2, danmuHead.MessageLength() - 2))
                    {
                        //使用内存流生成解压流(压缩流)
                        var deflate      = new DeflateStream(ms, CompressionMode.Decompress);
                        var headerbuffer = new byte[ProtocolHeadLength];
                        try
                        {
                            while (true)
                            {
                                await deflate.ReadAsync(headerbuffer, 0, ProtocolHeadLength);

                                danmuHead = DanmuHead.BufferToDanmuHead(headerbuffer);
                                var messageBuffer = new byte[danmuHead.MessageLength()];
                                var readLength    = await deflate.ReadAsync(messageBuffer, 0, danmuHead.MessageLength());

                                jsonStr = Encoding.UTF8.GetString(messageBuffer, 0, danmuHead.MessageLength());
                                if (readLength == 0)
                                {
                                    break;
                                }
                                json = JObject.Parse(jsonStr);
                                _messageDispatcher.DispatchAsync(json, _messageHandler);
                            }
                            continue;
                        }
                        catch (Exception e)
                        {
                            //读数据超出长度
                            Debug.WriteLine(e);
                            throw;
                        }
                    }
                }

                dataBuffer = new byte[danmuHead.MessageLength()];
                await _roomStream.ReadAsync(dataBuffer, 0, danmuHead.MessageLength());

                tmpData = Encoding.UTF8.GetString(dataBuffer);
                try
                {
                    json = JObject.Parse(tmpData);
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                    throw e;
                }
                if (!"DANMU_MSG".Equals(json["cmd"].ToString()) && !"SEND_GIFT".Equals(json["cmd"].ToString()))
                {
                    _messageDispatcher.DispatchAsync(json, _messageHandler);
                }
            }
        }