• QQ通信协议


    不管UDP还是TCP,最终登陆成功之后,QQ都会有一个TCP连接来保持在线状态。这个TCP连接的远程端口一般是80,采用UDP方式登陆的时候,端口是8000。因此,假如你所在的网络开放了80端口(80端口是最常用端口。。就是通常访问Web的端口,禁掉它的话,你的网络对你来说价值已经不大了),但没有屏蔽腾讯的服务器IP,恭喜你,你是可以登陆成功QQ的。

    二、聊天消息通信。

        采用UDP协议,通过服务器中转方式。因此,现在的IP侦探在你仅仅跟对方发送聊天消息的时候是无法获取到IP的。大家都知道,UDP 协议是不可靠协议,它只管发送,不管对方是否收到的,但它的传输很高效。但是,作为聊天软件,怎么可以采用这样的不可靠方式来传输消息呢?于是,腾讯采用了上层协议来保证可靠传输:如果客户端使用UDP协议发出消息后,服务器收到该包,需要使用UDP协议发回一个应答包。如此来保证消息可以无遗漏传输。之所以会发生在客户端明明看到“消息发送失败”但对方又收到了这个消息的情况,就是因为客户端发出的消息服务器已经收到并转发成功,但客户端由于网络原因没有收到服务器的应答包引起的。

    三、文件/自定义表情传送。

        大家都知道,QQ可以传送文件,可以发送自定义表情。先说官方表情。官方表情实际发送的是命令字,而没有发送表情。客户端收到命令字后,会自动解释为对应的表情。因此,QQ2008正式版的客户端发出的新版表情,在2007beta4及以前的版本无法找到相对应的表情,就无法解释,看到的就会是空白信息,但查聊天记录就会有[表情]字样。

        自定义表情的传送是以文件传输方式进行的。

        下面说文件传输方式:A要向B发送一个文件,于是发出一个文件传送请求。服务器收到这个文件传送请求后,转发给B,同时或者在B应答后,将A的IP地址同时发送给B。B这个时候就得到了A的真实IP。这里的IP是你的本机IP。也就是说,如果A处在内网,B得到的地址就是一个内网地址。B得到了A的地址之后,就会尝试去连接A。如果B也处于内网,那么,显然A跟B之间的连接是无法建立的。这个时候,客户端就会请求服务器进行文件中转。因为服务器具有公网 IP,处在内网的A跟B都是可以连接到服务器的,于是,A跟B的文件传送就通过服务器中转的方式,顺利进行。(注:服务器文件中转使用443端口)

    *   注:什么是内网、公网

        内网、公网是两种Internet的接入方式。

        内网接入方式:上网的计算机得到的IP地址是Inetnet上的保留地址,保留地址有如下3种形式:

       10.x.x.x

       172.16.x.x至172.31.x.x

       192.168.x.x

        内网的计算机以NAT(网络地址转换)协议,通过一个公共的网关访问Internet。

        内网的计算机可向Internet上的其他计算机发送连接请求,但Internet上其他的计算机无法向内网的计算机发送连接请求。

        公网接入方式:上网的计算机得到的IP地址是Inetnet上的非保留地址。公网的计算机和Internet上的其他计算机可随意互相访问。

        所以,如果一个局域网只开放80端口,QQ是可以登陆成功的,也可以进行聊天。但传送文件也是不可以的,除非你们都在同一个内网。如果局域网还同时开放443端口,那么,恭喜你,QQ的功能你都可以正常使用。

    QQ是不是TCP和UDP一起用?如果用UDP,如何做到信息的可靠发送? 

    答Q即可以使用TCP也可以使用UDP,但QQ默认是使用UDP协议,因为UDP协议消耗资源小,发送速度快,但当UDP协议不能正常转发的时候,就会采用TCP协议进行发送. 

    而信息的可靠发送是通过各种验证机制来完成的,这一点你可以去GOOGLE之类的网站去搜索下. 

    QQ用的是UDP打洞技术还是HTTP遂道? 

    答:发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是TX自行开发的

    因为用户一般都是在局域网内,地址都为私有IP,IM服务器是如何将信息转发到用户的? 

    答:如果使用TCP就没什么好说了~由内网向外网连接,只要能够连接上进行握手了,消息就可以畅通无阻的进行发送了.如果使用UDP的话,就是使用的打洞技术了,只要通道打通了,发送消息基本和TCP没什么区别,要做的只是维护消息的完整性而已.

    QQ是一个基于TCP/UDP协议的通讯软件,而MSN是基于TCP协议的通讯软件。

    那么QQ是如何通讯的呢?在TCP/IP协议中,唯一标识一个应用进程的是socket,它通过网络层的IP地址和传输层的端口号来实现,对与同一个IP地址的内部网络,通过不同的端口号来标识不同的QQ进程;当你登陆​ ​QQ游戏​​服务器的时候,服务器会保留你的保留IP地址和端口号信息,并在你的好友的QQ进程中进行列表显示,然后两个进程就可以通信了。 

      通常,发送文件的计算机首先要通过消息服务器将其IP地址发送给接收计算机,当接收计算机同意接收的确认消息反馈到消息服务器后,消息服务器将据此设置好文件传输对话。随即,发送计算机与接收计算机就会在确定好的端口范围内,建立起TCP或UDP连接开始文件的检索与传输。 

      在默认状态下,QQ优先采用了UDP(User Data Protocol,用户数据报协议)协议传送数据,而对可靠性要求高的数据通讯系统往往使用TCP协议传输数据。与TCP协议不同,UDP协议并不提供数据传送的验证机制——在整个文件传输过程中如果出现数据报的丢失,协议本身并不能作出任何的检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。 

      UDP协议适用于无须应答、要求时效的软件使用,这样的设计正好与QQ追求的目标相符,所以QQ优先使用了此协议进行一切功能应用。但是,由于  UDP协议具有不可靠性,常会因种种原因导致消息或数据的发送失败(很多时候会发现发送文件给对方接收时,对方根本收不到要求接收文件的消息。或是发送聊天消息时,对方根本没有收到过消息)。显然,UDP协议由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。QQ在数据传输上更注重实际性能,为了获得更好的使用效果,往往可以牺牲一定的可靠性。因此,使用QQ来传输数据,在很多时候就成了一个“不错”的选择。 

      一般内网传输首选QQ,速度最快,QQ的文件传输是直接个人对个人,采用P2P的传输方式,具有不需中转的优势,而且服务器都在国内,传输性能要高于外国IM软件。
     

    QQ协议首选的传输层是UDP,如果UDP不可登陆,那么会再尝试使用TCP进行传输。UDP使用的端口是8000,TCP使用的端口是443,应用协议基本一样,只是在通过TCP进行传输时,前两个字节为协议内容的长度(包括2个字节)。

    QQ协议中每个通信内容都带有一个协议头部

    其中标识占一个字节,版本号、命令字和序号都是2个字节,QQ号码有4个字节,接下来是数据部分(已加密),最后是一个尾部标识1个字节。

    在进行协议还原的时候,最关心的就是协议头部的命令字,需要根据不同的命令字,来进行相应的处理,最终获取密钥解密聊天内容。

    在2012这一个版本出来之前,接触包的命令是0091,不过QQ2012之后现在的接触包是0825。

    分析最新的qq2014,发现特征码是0828,客户端的特征串是  02 00 00 00 01 01 01 00 00 67 49

    QQ协议的所有包体都有一个很明显又固定的特征,那就是它每一个包体的未加密部分基本相同,加密部分也能通过未加密部分找出密钥来解密包体。

    包结构类型: 

    TCPF包我们把它分为5类: 

    登录请求包(LIP,LogIn Packet),它是由客户端向服务器发出登录请求的数据包。 

    登录应答包(LRP,Login Reply Packet),它是由服务器响应客户端登录请求的数据包。

    注销请求包(LOP,LogOut Packet),它是由客户端向服务器发出注销登录请求的数据包,服务器对这个包不作应答。 

    客户端其它包(CSP,Client Sent Packet),它是由客户端向服务器发送的其它包。

     服务器其它包(SSP,Server Sent Packet),它是由服务器向客户端发送的其它包。

      包头: 

    所有TCPF包的前7个字节是包头,包头可以识别TCPF包的内容。包头的格式为: 

    第0字节:TCPF包标识:0x02。 

    第1-2字节:发送者标识。如果是0x01 0x00,表明是由服务器发送。客户端的标识与所使用的使用的QQ版本有关,目前最新版本QQ2003(0808)的标识为0x0A 0x1D。具体的协议的格式与这个字段所标识的客户端版本有关。目前我们以这个最新的0A1D版本来讨论。 

    第3-4字节:命令编号。具体的命令编号含义在《QQ协议概述》(Protocol Overview.rtf)中有描述。如果这个字段是0x00 0x01,那么这是一个注销请求包。如果这个字段是0x00 0x22,而发送者标识是0x01 0x00,那么这是一个登录应答包。如果这个字段是0x00 0x22,而发送者标识是其它(例如0x0A 0x1D),那么这是一个登录请求包。其它的命令代码表明是其它包,我们通过发送者标识来区分它是CSP还是SSP。 

    第5-6字节:命令序列号。客户端和服务器都有各自的当前发送序列号。每初始发出一个指令的时候,使用当前的序列号,然后把当前序列号加一,如果超过0xFFFF,就绕回。如果是响应对方发出的命令,则使用这个命令的序列号。例如,客户端当前的序列号为0x1110,它向服务发送一个0x0016命令,它使用0x1110这个序列号,服务器收到以后,返回一个序列号为0x1110的0x0016命令响应。下一次,客户端又发送一个0x0026命令,这一次它使用加一了的序列号0x1111,服务器也响应0x1111序列号的一个0x0026命令响应。如果这是服务器要向客户端发送0x0017命令,它使用它自己的当前序列号,比如说0x2220,客户端收到以后,也响应一个序列号为0x2220的0x0017命令应答。我们可以通过序列号来判断发出的指令是否已经得到了应答,如果没有,可以重发。服务器对收到的命令的序列号顺序没有要求。服务器也不会一定按照发出的顺序给予应答。  

    包尾: 

    所有的TCPF包都以0x03作为包尾。在包头和包尾中间的包数据则不同类型的包有所不同。 

    LIP包: 

    登录请求包的包数据格式为: 

    第7-10字节(4 bytes):发出登录请求的QQ号码。这是一个Big Endian(高位在前)的unsigned long型数值。例如:0x01 0x82 0x5D 0x90就是0x01825D90,转换为十进制是25320848,表明发出请求的QQ号是25320848。 

    第11-26字节(16 bytes):随机密钥。这个密钥由于加密后面的数据。QQ使用TEA算法来加密数据。它使用的是128bit(16 bytes)的密钥。在0A1D版本中,这个密钥已经固定为16个01。 

    第27-106字节(80 bytes):加密后的登录包数据。  

    LRP包: 

    从第7字节开始到包尾前:加密的登录应答包数据。解密的密钥随客户端版本的不同,有不同的可能。在旧有版本中,使用登录包的随机密钥,在后期的版本,使用用户QQ密码的MD5 Digest。在0A1D中,使用QQ密码的MD5 Digest的MD5 Digest(这体现了腾讯有多么的愚昧和无耻,为了改变而改变)。LRP包内数据很重要的是16个字节的Session Key,它用来作为以后通讯的加密密钥。  

    LOP包: 

    它的序列号总是0xFFFF。不过,在新的版本中,好象已经没有了这个要求。 第7-10字节(4 bytes):发送注销登录请求的QQ号码。 

    第11字节到包尾前:加密的注销登录包数据。使用Session Key作为密钥。  

    CSP包:

    第7-10字节(4 bytes):发送请求的QQ号码。

    第11字节到包尾前:加密的包数据。使用Session Key作为密钥。  

    SSP包: 

    从第7字节开始到包尾前:加密的服务器发送包数据,使用Session Key作为密钥。  

    QQ加密算法概述: 

    QQ使用的加密算法来源于一种称为TEA(Tiny Encryption Algorithm)加密算法。它是在1994年由英国剑桥大学的David Wheeler和Roger Needham所发明的一种加密方法。大概来说,它是使用128bit密钥加密64bit数据产生64bit输出的一种算法。这种算法的可靠性是通过加密轮数而不是算法的复杂度来保证的。

    QQ使用的加密算法来源于一种称为TEA(Tiny Encryption Algorithm)加密算法。它是在1994年由英国剑桥大学的David Wheeler和Roger Needham所发明的一种加密方法。大概来说,它是使用128bit密钥加密64bit数据产生64bit输出的一种算法。这种算法的可靠性是通过加密轮数而不是算法的复杂度来保证的。具体的算法可以参考:。实现可以参考:。

      QQ使用16轮的加密(这是最低限,推荐应该是32轮)。

      QQ在使用这个算法的时候,由于需要加密不定长的数据,所以使用了一些常规的填充办法和交织算法(也就是说,把前一组的加密结果和后一组的进行运算,产生新的结果)。

      具体的填充算法是:原始字符串加上8个字节再加上填充字符数应该是8的倍数(至少填充2个字节)。填充后的字符串是这样组织的。第一个字节,为填充字符数减2 OR 上0xA8。后面是填充字节。然后是待加密的数据,最后是7个0。填充的字节一般是0xAD,但再0A1dD版本中,会使用随机的填充字符串。一般,我们会用解密后最后是否7个零来判断是否正确的解密。

      交织算法:第一个64bits块,按照一般的TEA加密。下一个64bit块与上一组的加密结果XOR生成待加密数据,加密后与上一组的待加密数据XOR生成加密结果。

  • 相关阅读:
    【深度学习】PyTorch深度学习笔记02-线性模型
    遗传算法------微生物进化算法(MGA)
    Cell:代谢组学肠道微生物群介导生酮饮食的抗癫痫作用
    01、Windows 常用的 DOS命令:
    MySQL分布式事务xa的介绍与使用
    LeetCode 热题 C++ 85. 最大矩形
    如何设置微信自动回复?教你快速上手!
    第十章 将对象映射到 XML - 控制关系映射的形式
    使用 SQL 加密函数实现数据列的加解密
    jscpd对项目进行查重(支持150+类语言)
  • 原文地址:https://blog.csdn.net/q2919761440/article/details/133468974