惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园_首页
雷峰网
雷峰网
V
Visual Studio Blog
爱范儿
爱范儿
A
About on SuperTechFans
量子位
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MongoDB | Blog
MongoDB | Blog
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
月光博客
月光博客
S
SegmentFault 最新的问题
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More

博客园 - LittlePeng

ffmpeg+x264 Windows MSVC 静态编译 NodeJS Addon 多线程通信 c coroutine leveldb(ssdb)性能、使用场景评估 [微信协议分析] 多媒体 [微信协议分析] 文本消息 paxos(chubby) vs zab(Zookeeper) 分布式一致性算法 erlang 健壮性 tcp 出现rst情况整理 tcp_tw_reuse、tcp_tw_recycle 使用场景及注意事项 erlang 在线生成crashdump erlang 故障排查工具 erlang 虚机crash Erlang C1500K长连接推送服务-内存 Erlang C1500K长连接推送服务-性能 redis lua erlang 虚机性能调优 java问题排查总结
[微信协议分析] 多点登陆
LittlePeng · 2015-01-03 · via 博客园 - LittlePeng

声明:微信客户端协议是二进制协议而且加密,难以分析协议具体编码格式,我不做逆向工程。只是简单抓包分析业务的实现流程,在这里记录下来用于参考学习,并不是破解协议。

  IM产品的多点登陆逻辑特别复杂,很难做到很好的用户体验,就像新版mac handoff 功能也不少人在喷。

  微信最开始并不支持多点登陆,后来陆续增加的Web版、Mac版,但并不是完整意义的客户端,要说只是辅助输入。

  微信允许: 一个移动端(下面称之为主客户端) + 一个web/mac 同时在线(下面称之为从客户端),web/mac 只能接收在线消息、发消息,不记录消息历史。这样多点逻辑就变得相对简单很多了。

  存储

  服务器不用保存完整消息历史,通过客户端对push消息的ack保证消息送达,协议保证消息至少一次推送到主客户端,然后消息即可删除;服务器只存储未下发到主客户端的消息。

  多点时:主客户端依然采用Push推送消息(只是应该会保留一小段时间消息记录等待从Sync),从客户端Sync消息;如果主不在线,消息记录不会删除,等主重新连上下载离线消息。

  服务器不存储消息历史,一个是安全,再者节省硬件成本,大量短消息的存储和读取成本是非常高的,因为基本都是随机IO。whatapp 用500台机器,支撑1亿在线,虽然有100w/s 消息,只离线消息存储量是很少的。

 未读数同步

   这个很好解决,如果客户端知道自己处于多端在线情况下时,进入会话时,需要告诉服务器消息已读。消息已读也保存为一条消息,再通过Sync协议,同步到另外的客户端。web 微信会调用webwxstatusnotify 同步未读。

  未读变化也当成一条消息存储,且只在多端情况下存在,单点在线时未读数由客户端维护。

  删除消息

  不管是否多点在线任何删除消息操作都会同步到服务器,避免删除的消息下次有不小心同步回来了,服务器可能及时删除、也可能长期保存,客户端每次上报就没错了。

  移动客户端消息删除不会同步到 web版。

 自己同步自己

   每个操作(发消息、清未读等),应答后,因为SyncKey 变化了,Sync协议上会产生一个空的Sync操作用于更新SyncKey。

   为啥不通过应答更新SyncKey?  并发情况直接更新会造成丢消息问题,也保证协议的统一性。

  对于主客户端:

  - 单点在线时发消息,并不会同送空的SyncKey,SyncKey应该是通过应答防护,节省同步流量。怎么防止丢消息呢?

   猜想是这样: 请求时带上SyncKey(local), 服务器在inc SyncKey得到SyncKey(current) == SyncKey(local) 时,直接返回SyncKey(current),否则返回Sync(local) 并推送New SyncKey Notify。因为此时确保客户端没有未收消息,坏情况应答比新消息慢,也不会有啥问题。

    - 多点在线时,发消息和从客户端一样,也会自己同步自己