一.朋友圈的基本单元——动态

首先定义一个自定义控件用来显示每条动态。

二.运行效果

      

三.核心解读

PushedMessage 有个PushIndex属性,表示发送消息的index,从0开始递增。每个人Push的index都是从0开始,ResponseMoments 的 MessageList 是个字典,Key表示 index。

        //
// 摘要:
// 拉取我的朋友们发的消息。当收到服务器回复,将触发ResponseMomentsReceived事件。
//
// 参数:
// startPullIndex:
// 从哪个index的消息开始拉取(不包含该index对应的那条)。如果startPullIndex小于0,表示拉取最新的N条。
//
// latest:
// latest为true,表示拉取更新的(大于startPullIndex);为false表示拉取之前的(小于startPullIndex)。
void Pull(long startPullIndex, bool latest);
//
// 摘要:
// 拉取目标用户所发的消息。当收到服务器回复,将触发ResponseMomentsReceived事件。
//
// 参数:
// ownerID:
// 所要拉取的目标用户的ID
//
// startPushIndex:
// 从哪个index的消息开始拉取(不包含该index对应的那条)。如果startPushIndex小于0,表示拉取最新的N条。
//
// latest:
// latest为true,表示拉取更新的(大于startPullIndex);为false表示拉取之前的(小于startPullIndex)。
void Pull(string ownerID, long startPushIndex, bool latest);

当调用这个方法时,表示获取我的朋友们的动态,我朋友们的动态会排序,index就是用这个key表示的。

latest 参数 表示是下拉,还是上拉。

四.DynamicsLoader解读

DynamicsLoader中最主要的是Load方法。

  public void Load(Dictionary<long, PushedMessage> currentMessageList, FlowLayoutPanel flowLayoutPanel, IMomentsClient client)
{
this.preLastIndex = this.lastIndex;
foreach (var item in currentMessageList)
{
if (this.firstIndex < )
{
this.firstIndex = item.Key - currentMessageList.Count + ;
}
if (item.Key < this.firstIndex)
{
this.firstIndex = item.Key;
}
if (item.Key > this.lastIndex)
{
this.lastIndex = item.Key;
}
if (!this.messageList.ContainsKey(item.Key))
{
this.messageList.Add(item.Key, item.Value);
}
}
this.freeIndex = this.lastIndex - ; if ((this.lastIndex - this.preLastIndex) > )
{
this.firstIndex = this.lastIndex - currentMessageList.Count + ;
this.preLastIndex = this.firstIndex;
this.freeIndex = this.preLastIndex;
this.messageList.Clear();
this.messageList = currentMessageList;
}
this.listIndex = new List<long>((IEnumerable<long>)this.messageList.Keys);
this.listIndex.Sort();
flowLayoutPanel.Controls.Clear();
foreach (var item in this.listIndex)
{
DynamicsControl crl = new DynamicsControl();
crl.Initialize(this.messageList[item].OwnerID, Encoding.UTF8.GetString(this.messageList[item].Content), this.messageList[item].PushTime);
flowLayoutPanel.Controls.Add(crl);
flowLayoutPanel.Controls.SetChildIndex(crl, );
}
this.listIndex.Clear();
this.listIndex = null;
if (this.isUp)
{
if (flowLayoutPanel.Controls.Count != )
{
flowLayoutPanel.ScrollControlIntoView(flowLayoutPanel.Controls[]);
}
}
else
{
if (flowLayoutPanel.Controls.Count != )
{
flowLayoutPanel.ScrollControlIntoView(flowLayoutPanel.Controls[flowLayoutPanel.Controls.Count - ]);
}
}
if (currentMessageList.Count == )
{
return;
}
if ((this.lastIndex - this.preLastIndex) < )
{
return;
}
do
{
client.Pull(this.freeIndex, false);
this.freeIndex -= ;
}
while (this.freeIndex > this.preLastIndex);
}

正如前面所言,每一条动态都有一个index,那么我每次获取动态的时候,就需要保留一个最小的索引,用于下拉的时候使用;保留一个最大的索引,用于上拉的时候使用。当最新的动态比本地的动态多出20条以上时,则分为两种情况:1.两次可以加载完的就加载两次 ,2两次无法加载完的,就只加载最新的20条,并将本地旧动态全部删除。

五.移动端如何通信

一.消息编解码总体策略

NPush默认使用紧凑的序列化器,其遵循的策略如下:
字符串一律使用UTF-8编码。如果是基础数据类型,则直接记录其字节。
如果是bool,则用一个字节表示,0表示false,1表示true。
如果是string,先记录其长度(int,-1表示为null,0表示string.Empty),再记录UTF8编码的字节。
如果是byte[],先记录其长度(int,-1表示为null),再记录其内容。
如果是Image ,先记录其长度(int,-1表示为null),再记录是否为Gif(一个byte),再记录序列化内容。
如果是Color ,长度固定为3个字节,一次记录R/G/B的值。
如果是List<>,先记录元素数(int,-1表示为null),再依次记录每个元素的内容。
如果是Dictionary<,>,先记录元素对的个数(int,-1表示为null),再依次记录每个元素的Key,Value。
如果是自定义的class和struct,则先记录其序列化的长度(int,-1表示为null),再记录其序列化后的内容

二.消息头

消息头固定长度为8。

以登陆请求消息为例:LoginContract,C->S,MessageType为0

三.消息

DeviceType取值: 0 - DotNet ,1 - Android ,2 - iOS

六.序列化原理

在分布式通信系统中,网络传递的是二进制流,而内存中是我们基于对象模型构建的各种各样的对象,当我们需要将一个对象通过网络传递给另一个节点时,首先需要将其序列化为字节流,然后通过网络发送给目标节点,目标节点接收后,再反序列化为对象实例。

为了将业务对象转换为二进制流,大家通常有两种方案可以选择:使用.NET自带的二进制序列化器,或,先将业务对象转换为字符串(比如xml),再将结果用类似UTF8进行编码得到字节流。 然而这两种方案都有缺陷。

1..NET自带的二进制序列化器

缺点:强侵入性,序列化结果臃肿,其size巨大,效率低下,加密困难。

2.通过string进行中转

缺点:需要自己打造协议对象与字符串之间的相互转换、序列化之后的结果的Size取决于我们协议对象与字符串之间相互转换时所采用的规则,同样也取决于我们的耐心程度 、同.NET自带的二进制序列化器,对象属性值的读取/设置、对象的创建等通常也是基于反射的,所以,效率同样存在问题。

基于上述,我选择采用自己的序列化方式,性能较.NET自带的二进制序列化器提高了7~8倍。

七.源码下载

(说明:压缩包中有SQL脚本,我使用的是Mysql数据库。客户端登陆账号为test01~test99,以及默认的testQQ。相应的好友关系可以查看服务端的TestFriendProvider类。 )

     安卓客户端下载

——————————————————————————————————————

推荐阅读 :那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程

实现过程全纪录——自己写一个“微信朋友圈”(包括移动端与PC端)的更多相关文章

  1. Android 高仿微信朋友圈动态, 支持双击手势放大并滑动查看图片。

    转载请注明出处:http://blog.csdn.net/sk719887916/article/details/40348873 作者skay: 最近参与了开发一款旅行APP,其中包含实时聊天和动态 ...

  2. ionic 实现微信朋友圈分享的完整开发流程

    最近开始要着手负责开发ionic的项目了,一直很好奇想实现一个微信朋友圈分享的功能,所以我就网上找了找文章来练手实现,果不其然,找到了几篇,但是发现它们的流程都不太详细,清楚,直接,还有不少坑. 今天 ...

  3. iOS版微信朋友圈数据库的简要分析

    本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/4550523.html 之前写了一些关于微信聊天记录的博文之后,不少 ...

  4. 微信朋友圈如何同时分享(图片+文字) Android版

    以下是:微信朋友圈SDK 分享图片的代码,但只能分享图片,不能分享文字,如何才能图片和文字同时分享?求各位大神指教! public class MainActivity extends Activit ...

  5. 如何利用Python网络爬虫抓取微信朋友圈的动态(上)

    今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...

  6. 实训六(Cocos2dx游戏分享到微信朋友圈----AppID的获取)

    考虑把游戏分享到微信朋友圈,前面的博文已经写到,shareSDK是一个很好的选择,但是学习了几天时间,遇到了很多问题,与其在一棵树上吊死,还不如退一步海阔天空,先暂时放一放,于是我考虑了一下既然是分享 ...

  7. Android 仿微信朋友圈发动态功能(相册图片多选)

    代码分享 代码名称: 仿微信朋友圈发动态功能(相册图片多选) 代码描述: 仿微信朋友圈发动态功能(相册图片多选) 代码托管地址: http://www.apkbus.com/android-15276 ...

  8. python爬虫24 | 搞事情了,用 Appium 爬取你的微信朋友圈。

    昨天小帅b看到一些事情不顺眼 有人偷换概念 忍不住就写了一篇反讽 996 的 看不下去了,我支持996,年轻人就该996! 没想到有些人看不懂 这就算了 还来骂我 早些时候关注我的小伙伴应该知道我第一 ...

  9. (转载) listview实现微信朋友圈嵌套

    listview实现微信朋友圈嵌套 标签: androidlistview 2016-01-06 00:05 572人阅读 评论(0) 收藏 举报  分类: android(8)  版权声明:本文为博 ...

随机推荐

  1. js MD5加密后的字符串

    js MD5加密后的字符串 <script language="JavaScript"> /************************************** ...

  2. SQL truncate 、delete与drop区别

    SQL truncate .delete与drop区别 相同点: 1.truncate和不带where子句的delete.以及drop都会删除表内的数据. 2.drop.truncate都是DDL语句 ...

  3. hashmap如何初始化

    现在知道的有两种: 1) Map<String, String> hashMap = new HashMap<String, String>(){            {   ...

  4. KEIL MDK 查看代码量、RAM使用情况--RO-data、RW-data、ZI-data的解释(转)

    源:KEIL MDK 查看代码量.RAM使用情况--RO-data.RW-data.ZI-data的解释 KEIL RVMDK编译后的信息 Program Size: Code=86496 RO-da ...

  5. ucgui汉字库存放到外部的flash(控件可用)及写外部FLASH小软件

    源:ucgui汉字库存放到外部的flash(控件可用)及写外部FLASH小软件 如何将ucgui的汉字库存放到外部的flash memory(ucgui)(汉字库)(外部flash) ucgui的字库

  6. Grunt 入门

    转自:http://user.qzone.qq.com/174629171/blog/1404433906 Grunt被定义为:the javascript task runner. 什么算是Java ...

  7. HMM的概率计算问题和预测问题的java实现

    HMM(hidden markov model)可以用于模式识别,李开复老师就是采用了HMM完成了语音识别. 一下的例子来自于<统计学习方法> 一个HMM由初始概率分布,状态转移概率分布, ...

  8. Extjs4新特性

    Extjs 4相对于之前的版本作出了重大的修正.其中包括全新的类系统.新平台的引入.API的修整和加强还有新组件的引入(如新的图表和图形组件).Extjs 4提供更快速.更稳定的用户体验,并且让开发人 ...

  9. 在阿里云ECS(CentOS6.5)上安装tomcat

    切换到你要安装的目录下 命令: cd /home/ 下载你要安装的tomcat 命令: wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7. ...

  10. IOS开发-OC学习-常用功能代码片段整理

    IOS开发-OC学习-常用功能代码片段整理 IOS开发中会频繁用到一些代码段,用来实现一些固定的功能.比如在文本框中输入完后要让键盘收回,这个需要用一个简单的让文本框失去第一响应者的身份来完成.或者是 ...