有那么一个应用,同样的服务器端,同样的Wi-Fi网络下,Android连接速度总是慢过iphone一个数量级。起先怀疑跟Android的硬件有关,无奈的是通过3G甚至于2G EDGE无线连接,速度均超过Wi-Fi。然后这个责任就一把归结到了“Android不如iPhone”,“Android七拼八凑”之类无休止的平台沙文主义之上了。

接手这个问题之后,起先也是渺无头绪。先从服务器端的结构说起吧。


服务器端,很具有中国特色的电信、联通、移动3入口结构,分别通过DNSpod指定到了3台Haproxy前端,通过这3台Haproxy主机发送请求到3台Server,理所当然的3台Server公用一套数据层。通讯协议并非通用协议,为自身设计的一套基于XML的数据通讯协议,所有的通讯都是TCP的持久连接。服务器端结构

起初的弯路也是被平台沙文主义带到了一个误区,我总是觉得Android手机的问题很可能是硬件驱动对于wi-Fi的支持不好。于是找来了一部手机,几乎刷遍了所有能支持的通用Rom,无奈没有任何起色。(话说Android刷机真的会上瘾:mrgreen: )

然后就是怀疑Android的DNS跟iPhone的不同,无奈两部手机的DNS均是统一DHCP获得的。

回到网络层上来,通过在路由器上监控Android的连接,终于发现Android会有经常性的连接丢包,发起连接很容易失败。单由于是长连接的关系,一旦连接建立成功之后,后续的通许就会很畅通。

说实话,那个时候还是有偏见,认为可能是手机跟路由器的兼容有问题,于是更换了数个路由器,从802.11a一直测到802.11an!不加密的,WEP的,PSK的等等试了个遍,依旧没有进展。忽然发觉这种尝试很可笑,于是自己在内网中写了一个服务端模拟器,发觉没有出现丢包,连接通畅。于是在外网中试环境中,去掉了haproxy层,直连服务器,连接畅通!

问题已经大致上定位了,就是在Haproxy上!!难题才刚刚开始……

更换了多个版本的Haproxy,无效!

怀疑是Android的内核TCP设置有问题(比如滑动窗口,缓存之类的),由于Android本身就是一个Linux,直接Root之后(刷机积攒的经验啊!)把/proc/sys/net路径拷贝下来,一个个文件的对照,一个个配置的试了一天(触摸屏打字很痛苦啊),几乎已经按照服务器的要求配置了一台手机,毫无进展。

好吧,逼我动用终极手段了!数据截取!

刷回原版Rom,连接内网服务器模拟器,通过sniff对所有的通讯数据截包,区分iPhone和Android信包的不同。多次试验之后,发现iPhone和Android每次的信包大小均不一致。Android信包总是大个12字节,终于找到问题了!

net.ipv4.tcp_timestamps

这个内核开关的含义是会在每个信包前增加一个符合RFC 1323标准的时间戳,正好12位。这个配置中,基于Linux内核的操作系统包括Android是默认开启的,但BSD系统,包括iOS中类似的设置是关闭的。

把Rom刷回可root,直接修改内核这个配置,效果立竿见影!应该是解决问题了,但总不能告诉用户“如果你们用Wi-Fi连接不了主机就直接去修改内核配置!”。

分析下来整个问题应该如此:

Haproxy可能存在 bug,或者我们配置有误。Haproxy在转发时可能会出现畸变的数据包,导致数据无法被送达到服务层。但这种状况并不是每次都能被激发(我偏向解释为这是Haproxy的bug)。看了下Haproxy的文档,他们只能解包Http,对于非Http的tcp协议,更多的只是转发数据包而已。对于说为什么手机网络不会受这个影响,个人觉得Android并不是单纯的一个给手机准备的操作系统,移动网络配置并不是存在于内核之中的,电话也好,移动网络也好,是通过应用程序层实现的功能。

畸变的数据包

好吧,把Haproxy的主机全部设置为net.ipv4.tcp_timestamps=0,Android马上跟iPhone享受了同等的待遇。

总结:

Android是当前发行量最大的Linux版本。
纠结于“谁比谁强”之类的话题只会耽误事,把结论归结到类似的话题上更是无聊至极。只有用不好,没有不好用!
数据截取之类的所谓黑客技术,有时可以更快的找出问题。

更多相关文章

  1. pandaboard ES学习之旅——5 Android Linux内核源代码下载与编译
  2. 禁止手机横竖屏
  3. 基于Socket的Android手机视频实时传输
  4. Android手机震动抖动效果的实现
  5. Android VNC Server on G1 (PC 远程控制 Android 手机)
  6. Android 的网络编程(15)-Http JSon服务器端和客户端通信
  7. android获取手机通讯录联系人
  8. Android获取如何获取当前手机IP地址
  9. Android 如何获取手机内存大小,内置存储空间大小

随机推荐

  1. android 工程里缺少 R.java 文件原因和解
  2. j2me to android
  3. Handler机制分析
  4. Android系列(一) 要了解的Android的消息机
  5. Flutter与Android的差异性
  6. android系统学习笔记三
  7. Android(java)学习笔记120:Android中的Appli
  8. Android(安卓)8.0 新特性及开发指南
  9. Android系统架构
  10. 一个轻量级、高可用性的 Android(安卓)版