昨天终于将困扰自己接近一个月的一个问题解决了,心情既激动又有点无奈,激动的是自己一直以来的坚持得到了回报,无奈的是克服这个问题实在的花费了巨大的代价,走了很多不必要的弯路。但不管怎么样,这个问题让自己获益良多,值得记录下来,作以参考。
- 问题:
- 解决问题的思路和过程:
首先我们先是通过网络查找有无人遇到这方面的问题,有很多人看似遇到了同样的问题,但是网上没有现成的解决方案。
不得已,只能自己解决这个问题,那么首先是确认问题在哪个方面,我们起初怀疑是SIP服务器端的原因,于是就用其他的SIP语音客户端作测试,结果是X-lite等SIP语音插件可以和X-lite自身客户端和Spark语音插件打通并且有声音,这样来看,应该不是服务器端设置的问题。
然后我们怀疑是openfire服务器端的问题,但是经过研究发现openfire服务器不涉及到SIP语音过程中,而只是提供SIP账号和Spark账号的映射,具体的SIP通讯过程还是在客户端与SIP服务器端之间进行的。
我们又把目光集中到SIP协议上,经过网络抓包,我们研究了SIP协议头,对比了成功的通讯和上述不成功通讯的差别,结果发现SIP协议在接通后的一段时间内自动挂断,这里让我们百思不得其解,另外抓包时发现不成功的通讯的RTP流完全不通,这里由于对于协议不了解,只好去学习SIP协议和RTP协议,但是仍然没有结果。
无奈之下,我们只好开始研究Spark的SIP客户端源码,在这个过程中,又要去学习java的JMF多媒体框架,但是最终发现代码没有问题,可RTP流就是无法接通。
问题到这里遇到了死胡同,只好另外再想办法,于是我们又找了另外一个开源的Java SIP客户端jitsi,这个客户端互相之间是可以打通并且有声音的,于是想通过研究它的源码来解决上面的问题,可是由于对于底层的运行机理不了解,依然没有搞清楚问题。
到这步实在是没辙了,于是就考虑直接剥离jitsi客户端的SIP模块,然后将Spark客户端的SIP插件重写,可是这也不是一件轻松的活,因为jitsi应用了Apache的felix这样一个基于osgi的动态模块框架,因为涉及到模块之间的依赖关系而使剥离模块很困难。
恰好到此时,我碰巧用别的机器做了一下测试,结果竟然有声音!因为之前一直是我和一个同事的机器之间在测试通讯,没有成功,结果在别的机器上竟然是通的!这让我想到了被我们忽略的网络环境,然后测试了一下,果然,有的机器之间有声音,有的机器之间没有声音,因为我们公司的网络环境并不稳定!我们之前的解决思路有一大部分是错误的!幸好及时发现这个问题,不然可能是沿着之前错误的道路越走越远。
- 教训和收获
回顾上面这个问题的解决过程,我们在前几步就出现了失误,不应该一直在同样的两台机器上测试,而应该充分考虑网络的个别差异,这也可以说是一种巧合,可是严谨的解决问题的思路应该尽量避免这种巧合给我们工作带来的影响,在解决一件事情时要充分考虑各方面的因素,在我和我同事的工作中,一些非常“难以解决”的问题,一般并不是一些很高深的技术难题,恰恰相反,反而可能是一些与技术没有什么关系但是却不易注意的小问题。
当然,在教训的背后,也让我收获了很多东西,首先是信心,要对自己有信心,以现在看来,对于不了解linux、sip、rtp、xmpp,网络知识匮乏的我们,能够把一个完整的SIP服务搭建起来并且运行,实在是一件不可想象的事情,可是一步一步的也被我们搞出来了,可见所有问题在正确的方法下都是可以解决的,解决问题的关键不在于问题本身,而在于自己对解决这个问题有没有信心和决心,只有这样,你才会在不断地挫折之中逐渐找到正确的答案。