之前的文章里说明了怎么让LumaQQ.NET发送长消息,这里我们看看怎么让LumaQQ.NET支持接收长消息。

        其实QQ的服务器在发送长消息时,是将其拆分成几个短的消息来发送的,这点在上一篇发送长消息时,大家已经能看出来了。那么怎么将几个短消息合并成一个长消息呢。

        这里主要是用到了NormalIM的TotalFragments和FragmentSequence两个属性,FragmentSequence表示这个是第几个分片,基于0的index,TotalFragments表示一共有几个分片。

        由于收到消息时,不一定是按照顺序接收到的(网络延迟等原因),因此我们定一个Dictionary来管理分片。

private static Dictionary<int, Dictionary<int, byte[]>> NormalLongTextDict = new Dictionary<int, Dictionary<int, byte[]>>();
 
        然后在接收到消息的事件里,进行判断和组装
void MessageManager_ReceiveNormalIM(object sender, LumaQQ.NET.Events.QQEventArgs<LumaQQ.NET.Packets.In.ReceiveIMPacket, OutPacket> e)
{
    if (e.InPacket.NormalIM.TotalFragments > 1)//如果是长消息的分片
    {
        Dictionary<int, byte[]> TextFragment;
        if (!NormalLongTextDict.ContainsKey(e.InPacket.NormalIM.MessageId))//如果字典里没有缓存这个消息id
        {
            TextFragment = new Dictionary<int, byte[]>();
            TextFragment.Add(e.InPacket.NormalIM.FragmentSequence, e.InPacket.NormalIM.MessageBytes);//将分片加入以分片id为标示的分片缓存
            NormalLongTextDict.Add(e.InPacket.NormalIM.MessageId, TextFragment);//将分片缓存加入以消息id为标示的消息缓存
        }
        else
        {
            TextFragment = NormalLongTextDict[e.InPacket.NormalIM.MessageId];//取出分片缓存
            TextFragment.Add(e.InPacket.NormalIM.FragmentSequence, e.InPacket.NormalIM.MessageBytes);加入新的分片
            NormalLongTextDict[e.InPacket.NormalIM.MessageId] = TextFragment;放回消息缓存
        }
 
        if (TextFragment.Count == e.InPacket.NormalIM.TotalFragments)//如果所有分片都已经接收完毕
        {
            List<byte> LongTextBytes = new List<byte>();
            string LongText = "";
            for (int i = 0; i < TextFragment.Count; i++)
            {
                LongTextBytes.AddRange(TextFragment[i]);合并byte数组
            }
            LongText = Encoding.GetEncoding(QQGlobal.QQ_CHARSET_DEFAULT).GetString(LongTextBytes.ToArray());转为文字字符串
              NormalLongTextDict.Remove(e.InPacket.NormalIM.MessageId);//删除缓存
              e.QQClient.MessageManager.SendIM(e.InPacket.NormalHeader.Sender, string.Format("我收到你的消息:{0}", LongText);
        }
    }
    else
    {
        WriteError("收到好友:{0}/{1} 发来的信息:{2}", e.InPacket.NormalHeader.Sender, Nick, AnalyCustomFace(e.InPacket.NormalIM.MessageBytes));
        e.QQClient.MessageManager.SendIM(e.InPacket.NormalHeader.Sender, string.Format("我收到你的消息:{0}", e.InPacket.NormalIM.Message));
 
    }
 
 
}
posted @ 2008-04-22 17:21 蓝色的风之精灵 阅读(1635) 评论(9) 编辑

        默认LumaQQ.NET不支持发送长消息,只能文字量比较小的文字信息。其实在内部设计上,已经支持了分片发送的功能,只是没有去拆分实现。我们这就来自己实现它。

1.首先在QQGlobal里添加消息最长长度定义:

   1: /// <summary>
   2: /// 消息最大长度,QQ是最大699字节   LumaQQ里说最长是700,但是我试下来只能是699,700就会出错,不知道为什么
   3: /// </summary>
   4: public const int QQ_MAX_SEND_IM = 699;

 

2.修改MessageManager里其中2个SendIM的方法

   1: /// <summary>
   2: /// 发送普通信息
   3: ///  <remark>abu 2008-03-11 </remark>
   4: /// </summary>
   5: /// <param name="receiver">The receiver.</param>
   6: /// <param name="message">The message.</param>
   7: /// <param name="fontSytle">The font sytle.</param>
   8: public void SendIM(int receiver, string message, FontStyle fontSytle)
   9: {
  10:     int MaxByte = QQGlobal.QQ_MAX_SEND_IM;//取最长长度
  11:  
  12:  
  13:     if (Encoding.GetEncoding(QQGlobal.QQ_CHARSET_DEFAULT).GetBytes(message).Length > MaxByte)//判断是不是要分段发送
  14:     {
  15:         List<byte> messageBytes = new List<byte>();
  16:         messageBytes.AddRange(Utils.Util.GetBytes(message));
  17:         messageBytes.Add(0x20);//补一个空格,不补似乎也会出问题
  18:         int messageSize = messageBytes.Count;
  19:  
  20:         int totalFragments = ((messageSize % MaxByte) > 0) ? (messageSize / MaxByte + 1) : (messageSize / MaxByte);//计算分片数
  21:         for (int fragementSequence = 0; fragementSequence < totalFragments; fragementSequence++)
  22:         {
  23:             int index = fragementSequence * MaxByte;
  24:             int BytesSize = ((messageSize - index) > MaxByte) ? MaxByte : (messageSize - index);//不能每次都申请最大长度的byte数组,不然字体会出问题
  25:             byte[] messageFragementBytes = new byte[BytesSize];
  26:  
  27:  
  28:             messageBytes.CopyTo(index, messageFragementBytes, 0, BytesSize);
  29:             SendIM(receiver, messageFragementBytes, totalFragments, fragementSequence, fontSytle);
  30:  
  31:  
  32:         }
  33:     }
  34:     else
  35:     {
  36:         SendIM(receiver, Utils.Util.GetBytes(message), 1, 0, fontSytle);
  37:     }
  38: }
  39: /// <summary>
  40: /// 发送普通信息
  41: ///  <remark>abu 2008-03-11 </remark>
  42: /// </summary>
  43: /// <param name="receiver">The receiver.</param>
  44: /// <param name="message">The message.</param>
  45: /// <param name="totalFragments">The total fragments.总分块数</param>
  46: /// <param name="fragementSequence">The fragement sequence.当前当块序号</param>
  47: /// <param name="fontSytle">The font sytle.</param>
  48: public void SendIM(int receiver, byte[] message, int totalFragments,
  49:     int fragementSequence, FontStyle fontSytle)
  50: {
  51:     SendIMPacket packet = new SendIMPacket(QQUser);
  52:     packet.Receiver = receiver;
  53:     packet.Message = message;//Utils.Util.GetBytes(message);
  54:     packet.TotalFragments = totalFragments;
  55:     packet.FragmentSequence = fragementSequence;
  56:     packet.FontStyle = fontSytle;
  57:     QQClient.PacketManager.SendPacket(packet, QQPort.Main.Name);
  58: }
posted @ 2008-04-22 13:17 蓝色的风之精灵 阅读(2048) 评论(16) 编辑