实现过程全纪录——自己写一个“微信朋友圈”(包括移动端与PC端)
一.朋友圈的基本单元——动态
首先定义一个自定义控件用来显示每条动态。

二.运行效果

三.核心解读
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端)的更多相关文章
- Android 高仿微信朋友圈动态, 支持双击手势放大并滑动查看图片。
转载请注明出处:http://blog.csdn.net/sk719887916/article/details/40348873 作者skay: 最近参与了开发一款旅行APP,其中包含实时聊天和动态 ...
- ionic 实现微信朋友圈分享的完整开发流程
最近开始要着手负责开发ionic的项目了,一直很好奇想实现一个微信朋友圈分享的功能,所以我就网上找了找文章来练手实现,果不其然,找到了几篇,但是发现它们的流程都不太详细,清楚,直接,还有不少坑. 今天 ...
- iOS版微信朋友圈数据库的简要分析
本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/4550523.html 之前写了一些关于微信聊天记录的博文之后,不少 ...
- 微信朋友圈如何同时分享(图片+文字) Android版
以下是:微信朋友圈SDK 分享图片的代码,但只能分享图片,不能分享文字,如何才能图片和文字同时分享?求各位大神指教! public class MainActivity extends Activit ...
- 如何利用Python网络爬虫抓取微信朋友圈的动态(上)
今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...
- 实训六(Cocos2dx游戏分享到微信朋友圈----AppID的获取)
考虑把游戏分享到微信朋友圈,前面的博文已经写到,shareSDK是一个很好的选择,但是学习了几天时间,遇到了很多问题,与其在一棵树上吊死,还不如退一步海阔天空,先暂时放一放,于是我考虑了一下既然是分享 ...
- Android 仿微信朋友圈发动态功能(相册图片多选)
代码分享 代码名称: 仿微信朋友圈发动态功能(相册图片多选) 代码描述: 仿微信朋友圈发动态功能(相册图片多选) 代码托管地址: http://www.apkbus.com/android-15276 ...
- python爬虫24 | 搞事情了,用 Appium 爬取你的微信朋友圈。
昨天小帅b看到一些事情不顺眼 有人偷换概念 忍不住就写了一篇反讽 996 的 看不下去了,我支持996,年轻人就该996! 没想到有些人看不懂 这就算了 还来骂我 早些时候关注我的小伙伴应该知道我第一 ...
- (转载) listview实现微信朋友圈嵌套
listview实现微信朋友圈嵌套 标签: androidlistview 2016-01-06 00:05 572人阅读 评论(0) 收藏 举报 分类: android(8) 版权声明:本文为博 ...
随机推荐
- android 屏幕适配小结
做android开发,开源嘛,满市场都是凌乱的机型,总少不了适配这样或那样的型号.在这里分享一下自己在开发中用到的方法. 首先要介绍一下drawable-mdpi.drawable-hdpi-1280 ...
- PAT (Advanced Level) 1022. Digital Library (30)
简单模拟题. 写的时候注意一些小优化,小心TLE. #include<iostream> #include<cstring> #include<cmath> #in ...
- CodeForces 616D Longest k-Good Segment
用队列维护一下即可 #include<cstdio> #include<cstring> #include<queue> #include<algorithm ...
- 用Quick Cocos2dx做一个连连看(三)
做个日记吧. 最近比较忙,斗志也不高,昨天有点时间了,开始做了一下连接方法,一开始用的搜索算法,但是bug比较多,究其原因是对语法和算法都不是很熟悉. 然后昨天下午利用点时间用稍微通俗一点的连接算法, ...
- source command not found in sh shell解决办法
在Ubuntu系统中执行脚本的时候突然出现错误"source command not found in sh shell" 这个其实在Ubuntu 当中 执行脚本默认的使用的是da ...
- Linux 服务器 常规性能优化设置
为能使linux服务器能最大化的工作,通常需要对linux的通常设置做适当的更改,而这又往往会依据服务器的类型不同,而有所变化. 对于通常的多连接的服务器其参数设置,可在 /etc/sysctl.co ...
- 仿苹果短信(微信 ,qq)左划弹出菜单
难点: 1.功能的实现,左划.ListView的复用 2.单行显示,多行显示 3.ListView分割线.点击阴影,上下滑动左右滑动无阴影.多点触控改为单点触控 4.融球动画 http://blog. ...
- nginx 防 webshell 跨目录
对于在一台服务器上有多个虚拟主机的人来说,Apache有一个很好用的地方---配置php_admin_value,在里面配置一下 open_basedir就可以了. 但是Nginx却没有这样的设置 ...
- (简单) POJ 2502 Subway,Dijkstra。
Description You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of ...
- D. PolandBall and Polygon BIT + 欧拉公式
http://codeforces.com/contest/755/problem/D // 我也觉得非平面图不能用欧拉公式,但是也能过,不知道为什么.求大佬留言. 这题其实就是平面图,因为它有很多个 ...