📄 receiveimpacket.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq.packets.in;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.nio.ByteBuffer;
import edu.tsinghua.lumaqq.qq.PacketParseException;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.Util;
import edu.tsinghua.lumaqq.qq.beans.ClusterIM;
import edu.tsinghua.lumaqq.qq.beans.FileInfo;
import edu.tsinghua.lumaqq.qq.beans.FileTransferArgs;
import edu.tsinghua.lumaqq.qq.beans.NormalIM;
import edu.tsinghua.lumaqq.qq.beans.NormalIMHeader;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.beans.ReceiveIMHeader;
import edu.tsinghua.lumaqq.qq.beans.SMS;
import edu.tsinghua.lumaqq.qq.packets.BasicInPacket;
/**
* <pre>
* 别人发来的消息包,如果是普通消息,格式为
* 1. 头部
* 2. 发送者QQ号,4字节
* 3. 接收者QQ号,4字节
* 4. 包序号(并非我们发送时候的序号,因为这个是4字节,可能是服务器端得总序号)
* 5. 发送者IP,如果是服务器转发的,那么ip就是服务器ip, 4字节
* 6. 发送者端口,如果是服务器转发的,那么就是服务器的端口,2字节
* 7. 消息类型,是好友发的,还是陌生人发的,还是系统消息等等, 2字节
* 8. 发送者QQ版本,2字节
* 9. 发送者的QQ号,4字节
* 10. 接受者的QQ号,4字节
* 11. md5处理的发送方的uid和session key,16字节
* 12. 普通消息类型,比如是文本消息还是其他什么消息,2字节
* 13. 会话ID,2字节,如果是一个操作需要发送多个包才能完成,则这个id必须一致
* 14. 发送时间,4字节
* 15. 1字节未知
* 16. 发送者头像,1字节
* 17. 是否有字体属性,4字节,有一般是0x00000001
* 18. 消息的分片数,1字节
* 19. 分片序号,1字节,从0开始
* 20. 消息id,2字节,同一条消息的不同分片id相同
* 21. 消息类型,这里的类型表示是正常回复还是自动回复之类的信息, 1字节
* 22. 消息正文,0是分隔符
* 23. 字体属性,和SendIMPacket中的相同
* 24. 尾部
*
* 如果是系统消息:
* 1-7. 与普通消息相同,只不过7是0x0030,表示是系统消息
* 8. 系统消息类型,1字节
* 9. 系统消息长度,1字节
* 10. 系统消息
*
* 如果是来自绑定手机的手机短消息,格式为:
* 1-7. 与普通消息相同,只不过7是0x000B,表示手机短消息
* 8. 未知1字节,0x0
* 9. 发送者QQ号,4字节
* 10. 未知1字节,0x0
* 11. 未知1字节
* 12. 发送者名称,最多13字节,不足后面补0
* 13. 未知的1字节,0x4D
* 14. 消息内容,一直到结尾都是,这个包长度200字节,如果不足,后面补0
* 15. 尾部
*
* 如果是来自移动QQ用户的手机短消息,格式为:
* 1 - 13. 与绑定手机短信相同,只不过7为0x0013
* 14. 短信发送时间
* 15. 未知1字节,0x03
* 16. 短信内容,0结尾,最大160字节
* 17. 尾部
*
* 如果是请求传送文件,格式为
* 1 - 18. 与普通消息格式相同,差别只有12部分,为0x0035,表示是请求传送文件
* 19. 未用部分,全0,15字节
* 20. 传输类型,1字节
* 21. 连接方式,1字节
* 22. 请求者外部ip,4字节
* 23. 请求者QQ端口,2字节,如果连接方式为0x3,则这个部分没有
* 24. 第一个监听端口,2字节
* 25. 请求者真实ip,4字节
* 26. 第二个监听端口,2字节
* 27. 空格符0x20
* 28. 分隔符0x1F
* 29. 文件名,不定长,不包含路径名
* 30. 分隔符0x1F
* 31. 文件字节数的字符串形式加“ 字节”
* 32. 尾部
*
* 如果是接受传送文件的请求,格式为
* 1 - 18. 与普通消息格式相同,差别只有12部分,对于UDP请求,为0x0037
* 19 - 26 和0x0035时相同
* 27. 尾部
*
* 如果是通知文件传送的端口,格式为
* 1 - 18. 与普通消息格式相同,差别只有12部分,为0x003B,表示是通知文件传送端口
* 19 - 26 和0x0035时相同
* 27. 尾部
*
* 未知类型的群消息
* 1-7. 与普通消息相同,只不过发送者QQ号相当于是群的内部ID,7部分为0x0020
* 8. 群外部ID,4字节
* 9. 群类型,1字节
* 10. 发送者QQ号,4字节
* 11. 未知的两字节,全0
* 12. 消息序号,2字节
* 13. 消息发送时间,4字节
* 14. 未知的4字节
* 15. 后面的数据的长度,2字节
* 16. 以0结尾的消息内容
* 17. 字体属性,和SendIMPacket中的相同
* 18. 尾部
*
* 如果是讨论组或者多人对话消息,讨论组和多人对话属于临时群,格式为
* 1 - 7 部分与普通消息相同,只不过7部分是0x002A
* 8. 父群内部ID,4字节
* 9. 群类型,1字节
* 10. 讨论组内部ID,4字节
* 11. 发送者QQ号,4字节
* 12. 未知的两字节,全0
* 13. 消息序号,2字节
* 14. 消息发送时间,4字节
* 15. Version ID, 4字节,所谓version id,是我这里根据这个字段的意思乱编的。
* 其作用主要是标识群信息的版本,比如一开始,群内有两个人,这个时候版本是0,然后我删
* 除一个人,那么群的版本就要加1,于是就变成了1。然后我又加了2个人,于是版本再加1变成3,
* 假如我再删一个人又加一个人,那么版本就要加2变成5了。为什么要加2呢,因为我做了两次操作,
* 一次删,一次加,所以版本号加了2,你可能奇怪:为什么我不一次搞定,然后版本加1啊?因为
* QQ的协议就是这样,它的协议不能同时做删除和添加成员的操作,晕吧?所以我要做两次操作,
* 也就是要发两个包才能又加人又删人,所以版本号加了2。那么这个字段有什么用呢?主要是用来
* 通知客户端群内的成员变化了以便刷新,客户端对每一个群都要保存这么一个version ID,一旦
* 收到的消息大于我本地的version id,说明群内成员变了,于是就发个包过去请求得到目前的
* 成员列表。所以你会看到,QQ在发临时群消息的时候,成员如果变化了,会即时的反映出来,就是
* 如此实现的了。这个id不光是在修改成员的时候才变,修改基本信息也照样变,用来表示这个群的
* 信息修改过了。注意:这个version id是从0开始持续增长的,所以如果是固定群,这个version
* id,这个值可能会很大,因为它是固定的嘛,成员总是在变化,版本也就一直往上长了。
* 16. 后面内容的长度
* 17. Content Type, 2字节,0x0001表示纯文件,0x0002表示有自定义表情
* 18. 消息的分片数,1字节
* 19. 分片序号,1字节,从0开始
* 20. 消息id,2字节,同一条消息的不同分片id相同
* 21. 4字节,未知
* 22. 以0结尾的消息内容
* 23. 字体属性,和SendIMPacket中的相同
* 24. 尾部
*
* 如果是示范群或会员创建的群发来的消息,这些群都是固定群,格式为
* 1 - 7 部分与普通消息相同,只不过7部分是0x002B
* 8. 群外部ID,4字节
* 9. 群类型,1字节
* 10. 发送者QQ号,4字节
* 11. 未知的两字节
* 12. 消息序号,2字节
* 13. 消息发送时间,4字节
* 14. Version ID, 4字节
* 15. 后面内容的长度
* 16. Content Type, 2字节,0x0001表示纯文件,0x0002表示有自定义表情
* 17. 消息的分片数,1字节
* 18. 分片序号,1字节,从0开始
* 19. 消息id,2字节,同一条消息的不同分片id相同
* 20. 4字节,未知
* 21. 以0结尾的消息内容
* 22. 字体属性,和SendIMPacket中的相同
* 23. 尾部
*
* 如果是0x0041,可能是向服务器报告最后连接情况的包,格式为
* 1 - 27. 和0x003B时相同,差别只有命令不同,为0x0041
*
* 如果是取消传送文件请求,格式为:
* 1 - 18. 与普通消息格式相同,差别只有12部分,为0x0049,表示是取消传送文件
* 19. 未用部分,全0,15字节
* 20. 固定字节0x65
* 21. 尾部
* </pre>
*
* @see edu.tsinghua.lumaqq.qq.beans.NormalIM
* @see edu.tsinghua.lumaqq.qq.beans.NormalIMHeader
* @see edu.tsinghua.lumaqq.qq.beans.ReceiveIMHeader
* @see edu.tsinghua.lumaqq.qq.beans.ClusterIM
* @see edu.tsinghua.lumaqq.qq.beans.FileTransferArgs
* @see edu.tsinghua.lumaqq.qq.beans.FileInfo
*
* @author 马若劼
*/
public class ReceiveIMPacket extends BasicInPacket {
// 流对象
private ByteArrayInputStream bais;
private DataInputStream dis;
// 用于发送确认
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -