心跳一直在 230 秒感觉很费电,很影响续航。一开始以为是 wifi 网络问题,以为是 NAT 时间过短,就试着在路由器上转发一下增加一下 tcp 的 keepalive 。
于是在路由器上执行:
iptables -t nat -A PREROUTING -p tcp --dport 5228 -i wlan0 --to DNAT 192.168.1.1:5222
socat TCP-LISTEN:5222,fork,reuseaddr TCP:64.233.189.188,keepcnt=3,keepidle=300,keepintvl=60
然而半天测试下来,并没有啥用。
从抓包看,最后的断开地方,看到手机有发送 client heart beat, 但是收不到应用层的 ACK (但是看到 TCP 的 ACK 是有的,偶尔还看到 client heart beat 后还有接收到 server heart beat )。
初步觉得国内虽然 mtalk.google.com 没有直接阻断,但是还是有干扰,要么是靠近国内的 FCM 服务器不太稳定。
最后,尝试在路由器上建立 ipsec 隧道,然后让连接美国的 FCM 服务器 mtalk.google.com/74.125.137.188, 然后 ipsec 是走 udp 封装,所以就一直 ping 避免 UDP 的 NAT 失效。 目前测试下来,FCM 连接 7 个小时没有断开,并且心跳已经能够从 230 升到了 770,并且感觉手机电量也不再崩的那么快了。
所以,我觉得路由器上通过 UDP(udp2raw)转发 TCP/5228 流量应该是个不错的方案,比起直连好很多。
至于,移动数据网络上,我测试把 mtalk.google.com 域名解释道国内的机器上,然后在国内机器通过 UDP 把 TCP/5228 转发出去,测试下来心跳时间可以稳定到 1100 秒。
结论:不要在国内放任 FCM 直连,否则会影响续航以及推送的及时性。