飞信2010分析 – 使用HTTP模式和服务器通信
在 飞信2010分析 – SIPC验证 文章里,简单的提到了飞信使用HTTP传输模式。
HTTP模式是所有传输方式中效率最低,是在其他传输方式都建立失败后才会采用HTTP传输模式,可见飞信在网络环境适应上下了很大的功夫的。
在第一步获取自适应的配置中,曾经提到下面几个参数:
含义 位置 结果举例
SIPC-PROXY /config/server/sipc-proxy 221.130.46.141:8080
SIPC-SSL /config/server/sipc-ssl-proxy 221.130.46.141:443
HTTP-TUNNEL /config/server/http-tunnel HTTP://221.130.46.141/ht/sd.aspx
飞信建立连接主要就是这三个传输方式。
来看下飞信的建立连接的顺序:
第一步: 尝试连接建立 SIPC-PROXY连接 。 即SIPC服务器端口为8080的连接。 这是最稳定的,效率最高的传输方式。
第二步: 如果第一步失败,则尝试建立SIPC-SSL连接。 即SIPC服务器端口为443的连接。 和SIPC-PROXY连接方式完全一致,就是端口变了。虽说是SSL端口,却仍然没有加密;
第三步: 如果第二步失败,则尝试建立HTTP-TUNNEL连接。 即HTTP代理连接。 采用长连接的模式,效率比较低,而且不太稳定。不过只要能访问HTTP,就可以连接上飞信服务器。
第四步: 如果第三步建立失败,则飞信客户端和飞信服务器建立连接失败。
可以看出如果要分析HTTP模式,则需要把SIPC-PROXY和SIPC-SSL的IP和端口堵上。一般都是相同的IP不同的端口,可以使用防火墙来完成。
HTTP分析可以使用HTTPAnalyzer帮助分析。 在我的飞信资源整合那篇文章中有这两个工具的下载。
在分析之前,还是简单的介绍长连接模式。因为HTTP模式下就是使用了长连接的方式。
我们知道HTTP是一个请求-回复类型的协议。在发起一个请求之后,服务器需要返回一个回复。可以理解为是单向的,请求只能是浏览器发送,服务器只能被动的接受请求处理请求,并不能主动的和客户端发送消息。
在Socket通信模型中,客户端和服务器的通信是双向的,客户端可以主动的向服务器发送信息,服务器也可以主动的向客户端发送信息。这在即时通信里面很有必要,假如其他用户主动的发消息给你,服务器可以在第一时间内主动的发消息通知你。
飞信是需要双向通信的模式,但HTTP服务器是不能主动的给客户端发送信息的。于是产生了长连接的技术,也就是Comet,来模拟服务器主动给客户端发送消息。
长连接其实很简单,客户端主动的发起一个HTTP请求给服务器,服务器收到这个请求后,会查看是否有消息可以返回给客户端,如果有把消息放入回复体内,立即返回给客户端。如果没有,就阻塞掉这个请求,不返回,直到服务器有可以返回的消息或者超时才结束这个请求。客户端检查这个请求,如果是超时,就立即发起另外一个请求,如果不是超时,就处理服务器的返回的数据,处理完了继续发起下一个请求。
这样服务器就始终保留了一个客户端的连接,如果收到消息后就可以立即返回给客户端,完全可以模拟Socket双向的通信模式。
只不过这种模式效率低,而且不太稳定,服务器资源占用率大(因为要维持多个连接),不过在一些特别的情景下需要使用。目前WebQQ和WebFetion等即时通信的WEB都是采用了这样的通信模式。
详细的长连接信息请参见IBM工程师写的文章 – Comet:基于 HTTP 长连接的“服务器推”技术 。
分析很简单的,不罗嗦过程,直接写结果吧。
HTTP模式下,假如HTTP://221.130.46.141/ht/sd.aspx为获取自适应配置返回的HTTP-TUNNEL地址:
下面是一个HTTP请求的例子:
就着这个例子,逐步的分析。
请求的方式为POST。
在URL上面有两个参数:
t : 请求的模式,取值有 i,s,d,下面会有详细的说明;
i : 请求的序号,随着请求的次数递增;
还传递了一个Cookie: ssic。 ssic是SSI登录成功后,会在HTTP头中使用标准set-cookie方式返回;
在请求头中还有一个Pragma域,在整个请求中不变,可能是标志唯一的客户端。前面七个字符固定为xz4BBcV,后面是一个GUID,可以随机生成
其他可以保持不变。
请求体就是 SIPC信令包+SIPP。 请注意这里一定要加上SIPP四个字符,如果没有SIPC信令包,也要发送SIPP四个字符。信令包的内容和过程和SIPC-PROXY连接发送的内容是完全一样的。
但有一个包有点区别,就是第二步验证的时候 后面的值不同,在SIPC-PROXY和SIPC-SSL连接中这个值为1FFF,在HTTP模式下这个值为AFF。这个值的含义,是表明了客户端支持的特性。如果有时间可能会写文章来分析这个值代表的含义,但现在只需要知道,这个值影响的后面和在线的好友建立对话的方式。
请求的回复头没有什么有价值的东西,回复体就是 SIPC信令包+SIPP 。注意这里还是有个SIPP四个字符。如果有信令包需要返回给客户端就把信令包直接放在回复体中。服务器也可以不返回任何信令包,只返回一个SIPP。
基本的格式就是这样。下面看下过程。
简单的过程和建立一个对话很相似:建立连接 -> 发送消息,接收消息,发送消息,接收消息…..-> 关闭连接。
1、建立连接的过程很简单,参数t的值为i,POST的内容只有一个SIPP四个字符,如果返回200,建立连接成功;
2、发送和接收消息,请求体放置了需要发送的SIPC信令包,回复体中放置需要接收的SIPC信令包。 注意这里可能有多个信令包可以放入一个请求体或者回复体中。
如果没有任何SIPC信令包可以发送,仍需发送空的请求包(即只含有SIPP四个字符的请求体)给服务器建立长连接。服务器有消息就会把消息放入回复体中,立即返回这个请求,如果没有就阻塞这个请求,直到超时。
3、关闭连接的过程也很简单,参数的t为d,POST的内容只有一个SIPP四个字符,如果返回200,关闭连接成功;
下面是SSISignV4Test例子中的HttpTranfer.java的部分代码,实现了HTTP传输方式,各位可以参考下,完整的例子可以在首页的公告找到下载地址。
其实HTTP模式下的连接很简单,就是传输SIPC信令包的方式不同而已,其他的没有太大的变化。可以想象HTTP传输方式就是把SIPC-PROXY传输的信令包换了一种方式传输而已。
但有一点有很大的区别,就是HTTP模式下和PROXY,SSL模式下和在线好友建立对话的方式完全不同。这个会在下几篇文章中详细的分析。
HTTP模式就分析到这,下一篇分析在SIPC-PROXY,SIPC-SSL这两种模式下,如何和在线的好友建立会话。