原创

smack exception: No response from the server

smack exception: No response from the server (注意:不是No response from server)
产生的原因有多种:
1. MessageListener未能正确处理response,详情参见
http://community.igniterealtime.org/thread/33598
2. 网络连接出现问题,smack客户端没办法收到response,详情参见(需爬墙……)
http://davanum.wordpress.com/2007/12/31/android-just-use-smack-api-for-xmpp/

今天在服务器上重现了这个问题,间歇性返回No response from the server,但是网络连接状态相当好,到该服务器的http请求都顺利返回,而且速度很快,因此不是网络连接问题。同样,并不是每次返回都报错,60% 的尝试是能够成功的,因此也排除原因1

重现该exception的时候,虽然不是网络导致的原因,但是跟网络环境有密切关联:
1. 在非常稳定的网络环境下(ping值稳定在5ms左右,且没有明显的抖动)出现的概率非常小
2. 在网络抖动比较大的环境下,出现非常频繁

google说明,smack的这个exception,已经report在openfire和ejabberd上都重现过,因此证明,不是单一服务器代码的问题

通过检查smack源代码,查到No response from the server的exception出现在2个文件中:
NonSASLAuthentication.java:

Java代码  收藏代码
  1. IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
  2. if (response == null) {
  3.     throw new XMPPException("No response from the server.");
  4. }

SASLAuthentication.java:

Java代码  收藏代码
  1. Bind response = (Bind) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
  2. ollector.cancel();
  3. if (response == null) {
  4.     throw new XMPPException("No response from the server.");
  5. }
  6.     IQ ack = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
  7.     collector.cancel();
  8.     if (ack == null) {
  9.         throw new XMPPException("No response from the server.");
  10.     }

问题缩小到2个方面:resource bind失败,或者确实没有收到response包
由于这边的服务器采用的是NonSASL验证的方式,所以答案只剩下:确实没有收到response

在服务器上运行tcptrack,监控进入的连接,发现smack报错的时候,tcptrack的连接记录说明,该连接被reset了,也就是说,直接从syn-ack状态跳到了reset状态,因此客户端的连接直接就断开了,所以根本不可能收到response

而smack是个高度封装的库,可配置的参数非常有限,出了用户名和密码以外,跟底层链路相关的参数就只有:SecurityMode,初步判断 是该参数影响了连接,因此更改默认的enable为disable,也就是不使用TLS链路跟服务器进行通信。同样,服务器也禁用TLS之后,问题状况立 即得到改善。

结论:

TLS在TCP连接的基础上,需要消耗更多的网络资源和服务器资源,来进行加密运算,因此在网络抖动非常大,或者网络比较不稳定的状况下,会严重 影响通信连接,尤其是不停的断开重连,如果发现smack客户端有出现No response from the server的exception,可尝试更改连接选项,disable TLS来解决问题

正文到此结束
Loading...