C#服务端,Android客户端 开发IM,服务端怎么弄,有没有开源的框架

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#服务端,Android客户端 开发IM,服务端怎么弄,有没有开源的框架相关的知识,希望对你有一定的参考价值。

参考技术A   C#开源项目(国外的还是很多) 一、Ajax框架 Ajax.NET Professional
(AjaxPro)是最先把AJAX技术在微软.NET环境下的实现的AJAX框架之一。它在客户端脚本之上创建代理类来调用服务器端的方法。
MagicAjax.NET是一款在ASP.NET下创建Web页面提供AJAX技术的框架。它使开发人员很容易把AJAX整合到他们的页面而不需要替换ASP.NET控件或自己写javascript脚本代码。
Anthem.NET是为ASP.NET开发环境提供的开源AJAX工具包,它可以运行于ASP.NET 1.1和2.0。

  二、工作流(workflow)
Workflow.Net是使用微软.Net技术基于wmfc标准的创建工作流引擎。
NetBPM是JBpm移植到.net平台下的一款开源工作流软件。NetBpm可以很容易和.Net应用程序集成在一起,可以创建,执行和管理工作流程序。 Bpm
Tool支持将业务模型转换成软件模型。业务开发人员可以使用模型驱动的方法设计,实现,执行和跟踪业务流程。因此开发人员能够更容易的关注业务逻辑的变化。

  其实微软自己的WPF做WorkFlow也很厉害。

  三、文本编辑 FCKeditor是一款功能强大的开源在线文本编辑器(Dhtml
editor),它使你在web上可以使用类似微软Word 的桌面文本编辑器的许多强大功能。它是轻量级且不必在客户端进行任何方式的安装。 FreeTextBox
是一个基于 Internet Explorer 中 MSHTML 技术的 ASP.NET 开源服务器控件。这是一款优秀的自由软件(Free
Software),我们可以轻松地将其嵌入到 Web Forms 中实现 HTML 内容的在线编辑,在新闻发布、博客写作、论坛社区等多种 Web
系统中都会有用途。 VietPad是一个功能完整的跨平台的Java/.NET的Vietnamese
Unicode开源文本编辑器。支持打开,编辑,打印,转换,排序,和保存基于文本的Unicode格式的Vietnamese文件。
NetSpell是一款.NET框架下的开源拼写检查引擎。 PPC_edit是一款应用在Pocket PC上的开源文本编辑器,它支持TXT, RTF, HTML,
WordML, DocBook 和 ZIP格式的文件,屏幕上会显示国际标准的软键盘。

  四、博客(Blog)
NovaShare是一款Blog引擎,它使你创建基于交互式的web的新闻和论坛网站,很像WonkoSlice或Slashdot。管理员可以发布文章和发起投票,浏览者可以创建用户帐号,发表议论等等。
dasBlog是从BlogX 网上日志引擎发展而来。像Trackback ,Pingback
一样增加许多附加的特征,有完整的Blogger/MovableType
API支持,API注释,完整的Radio-style模板定制,支持Mail-To-Weblog/POP3的附件和内嵌图片,基于WEB的
DHTML,OPML,配置的编辑器。 DotText是一个被使用了数百个blogs的强劲的blog引擎。这是一个N-tiered应用的例子。
tBlogger是一个C#开发的完整的blog网站程序,使用XML配置。

  Blog现在可以使用MVC的其他开源项目来构建,这些项目在codeplex上有很多,其中微软自己的就有OXite。

  五、系统构建

  .NETZ是一款免费开源工具,它可以压缩和打包微软 .NET 框架可执行文件(EXE,
DLL)以使他们更小。更小的可执行文件占用的磁盘空间较少且因为读取文件时对磁盘的访问较少而使读取数度更快。它和PE(portable
executable)打包工具不一样,.NETZ是使用 C# 编写的存粹的 .NET 解决方案。.NETZ可以用来打包几乎每一种 .NET
支持的语言编写的程序。.NETZ支持 .NET EXE 和 非共享(non-shared)的 DLL
文件。压缩过的程序能以相同的方式解压缩这些对最终用户是透明的。 NAntContrib为NAnt提供定制任务的工具。
Prebuild是XML驱动的一款跨平台pre-build工具,使开发人员很容易就可以为IDE和.NET开发工具生成项目或构建文件。它支持 Visual
Studio .NET 2002, 2003, 2005, SharpDevelop, MonoDevelop 和 NAnt。
BusyBeeBuilder是.NET平台下功能强大,易于使用,可扩展的开源构建自动操作工具。 Draco.NET 是 Windows
服务应用程序。它的设计使其容易持续的集成新特性。Draco.NET监视你的源代码储存库。当探测到你的项目有变化时自动重新创建项目并把包含变化列表的创建结果发送到你的Email。
Build Studio为软件的自动构件处理提供了一套完整的解决方案。 CruiseControl.NET是.NET平台下的一款整合服务器。
NAnt类似Apache项目下的Ant,是.Net下的开源构建工具。适用在自动编译.NET应用的场合,如.NET项目的每日构建(nightly
build)。

  说老实话,我并不认为系统构建工具的作用真的有那么强大,如果你真的计划做一个很大的项目,且持续开发时间很长,那么你可以使用上面的系统构建工具。

  五、图表制作

  ZedGraph是C#编写的.NET类库,提供了用户控件和web控件。它可以创建2D的线性图、条形图和饼图。它功能完整且有详细的功能自定义,不过
使用默认的选项就足够好用了。一款类似 PieChart, StackBar, LineChart的C#开源图表组件。
NPlot是一款.NET下的开源图表类库.它值得称道的地方是优雅且灵活的API设计.NPlot包含了Windows Form控件,
ASP.NET控件和一个创建Bitmap图片的类。还有一个可用的GTK#控件。 XSCharting是C#开发的图表组件,提供了多种多样的图表选项。
DaveChart是一个免费的DotNet类库。 NChart 提供了很多值得应用在商业,教育等多个领域的2 D图表。

  微软自己已经提供了一个chat绘制控件,也就是原来的dunat,如果那个可以满足你的要求,那么完全没有必要使用上面的。但是如果你需要研究画图,作自己定义的chat,那么这些开源的项目将对你有很大的帮助。

  六、聊天系统

  Dot Net Chat
server是基于DotNet框架开发的聊天服务器和客户端项目。说老实话,我对这个很感兴趣,有时间,要瞧瞧它的代码是咋实现的。

  七、内容管理系统(CMS)

  Ludico是C#编写的居于ASP.NET
2.0的Portal/CMS系统。它的模块化设计是你可以按照你希望的使用或开发网站功能。它里面有高级的用户管理,一个所见即所的(WYSIWYG)的编辑器等。
mojoPortal是一款C#开发的面相对象网站框架,它可以运行于Windows的ASP.NET 和GNU/Linux 或Mac OS X的Mono的平台上。
Cuyahoga是C#开发的灵活的CMS / Portal 解决方案。它可以运行于Microsoft .NET 和Mono 平台,支持SQL Server,
PostgreSQL或mysql作为底层数据库。 Umbraco是一款在.net平台下C#开发的开源内容管理系统,该系统效率,灵活,用户界面都不错。 Kodai
CMS是.NET平台下的一款功能齐全的内容管理系统。 Rainbow项目是一款使用Microsoft’’s
ASP.NET和C#技术开发的有丰富功能的开源内容管理系统。 NkCMS是使用ASP.net和Sql server 2000开发的内容管理系统。
Amplefile是一款内容管理系统,是.Net环境下的windows应用程序,使用了.Net remoting.
Go.Kryo是一个用ASP.NET(C#).NET 实现的简单的内容管理系统,后台数据库使用Microsoft SQL Server 。 ndCMS是
ASP.net
(C#)下的一个内容管理系统。它提供了用户管理,文件管理,一个WYSIWYG编辑器,模板管理,拼写检查和内置的http压缩。ndCMS的目标是提供一个简单而快速的方式部署.Net站点以节省你的时间和金钱。

  这些开源的CMS我试用了几个,说真的,拿来研究可以,要真的实施,估计很难。

  九、论坛系统

  YetAnotherForum可以作为ASP.NET开发的网站的论坛或是留言板。它使用MSSQL作为底层数据库。

  十、安装制作

  izfree是一套套免费的工具用于帮助创建使用Microsoft”’’s Windows
Installer 技术的安装程序。使用izfree你可以为你的应用程序制作强劲的安装程序。

  Windows Installer XML
(WiX)可以重XML源文件创建Windows程序安装包的工具集。它支持命令行方式,开发人员可以把结合它来创建MSI和MSM安装包一个可以和商业软件安装产品相比的开源打包工具。

  一般的需求试用VS
自带的就可以了,更复杂的需要用到InstallShield,这样看起来开源的就没啥意义了。

  十一、IoC容器

  Spring.net是从java的Spring
Framework移植过来的。java的Spring包含了许多功能和特性,在当前的Spring.net都有提供。Spring.net最初发布的版本包含了一个很有特色的IoC容器。

  Castle是一组应用开发的工具,内含一个简单的IoC容器。

  StructureMap是.NET环境下的一个轻量级依赖注入工具,StructureMap也是一个灵活的、可扩展的通用“插件”机制的.NE

  我用过StrucutureMap,但是给我的感觉是,试用这个似乎没多发帮助。

  十二、网络客户端

  .NET FTP Client是C#编写的开源类库。

  .NET Telnet是微软.NET
Framework下的C#开发的开源telnet类库。它的灵感来至Java Telnet Application。

  metro这个项目是C#编写的类库,它提供了一套丰富的类使开发IP version 4, TCP,
UDP and ICMP等工作更容易。它包含了有很有用的工具如包嗅探器,网络分析工具例如路由跟踪,ping等。

  LJ.NET是LiveJournal站点的客户端。它为LJ在线日志服务提供了简单而强大的用户接口。

  NET VNC Viewer 是一款完全用C#开发的开源VNC观察器。它兼容Smartphones,
Pocket PC和Windows的电脑(.NET CF or .NET Framework)。它比起其它观察器的优点是可以在Pocket
PC上全屏显示而且可以旋转屏幕。

  GVDownloader允许你从google videos, metacafe, putfile,
youtube, break.com 和更多的地方快速下载内含的视频和多媒体。它的包含一个强劲IE插件和位于你系统托盘的独立程序。

  DotNetOpenMail能够使你在微软.net框架开发的asp.net,
WinForm应用程序发送Email。它是C#编写的开源组件,它不需要使用System.Web.Mail类库就可以容易的创建带附件HTML和
Plain-text的Email。程序员不需要知道很多相关的细节就可以使用不同的字符集或不同的MINE编码来创建
multipart/alternative,multipart/related和multipart/mixed的MIME消息。

  DotMSN是一款独立的开源类库,它不需要和官方的MSN Messenger交互,因此不必安装MSN
Messenger就可以使用DotMSN和MSN
Messenger服务通信.DotMSN是C#编写的,所以.NET环境支持的语言都能够使用.DotMSN类库使用简单而且实现方便。它灵活,坚固,
轻量级利于整合到任何应用系统.使用DotMSN的应用系统能实现从创建消息机器人到自定义客户端等各种不同的功能.如果你的应用程序需要和
Messenger服务通信,DotMSN是一个不错的工具.

  SharpSSH使用C#实现了SSH2协议,它支持SSH, SCP 和 SFTP.

  OpenPOP.NET一组和POP Servers通信的.NET类库。

  IceChat是为连接多样的IRC Servers设计的Internet Relay Chat
Client。

  lphant是为edonkey/emule开发的开源客户端程序。

  .NET FTP Client C#开发的类库。

  OpenSmtp.net 是 C# 开发的开源SMTP组件。它不依赖.NET Framework
的System.Web.Mail 包中的类。允许开发人员使用不同于MS SMTP的SMTP 服务器且提供了web
service而可以通过HTTP发送email。

  这里面有几个值得推荐,例如DotMsn这个,在某些场合就很有用处。

从零开始开发IM(即时通讯)服务端

好消息:IM1.0.0版本已经上线啦,支持特性

  • 私聊发送文本/文件
  • 已发送/已送达/已读回执
  • 支持使用ldap登录
  • 支持接入外部的登录认证系统
  • 提供客户端jar包,方便客户端开发

github链接: https://github.com/yuanrw/IM

本篇将带大家从零开始搭建一个轻量级的IM服务端,IM的整体设计思路和架构在我的上篇博客中已经讲过了,没看过的同学请点击从零开始开发IM(即时通讯)服务端

这篇将给大家带来更多的细节实现。我将从三个方面来阐述如何构建一个完整可靠的IM系统。

  1. 可靠性
  2. 安全性
  3. 存储设计

可靠性

什么是可靠性?对于一个IM系统来说,可靠的定义至少是不丢消息消息不重复不乱序,满足这三点,才能说有一个好的聊天体验。

不丢消息

我们先从不丢消息开始讲起。

首先复习一下上一篇设计的服务端架构
技术图片

我们先从一个简单例子开始思考:当Alice给Bob发送一条消息时,可能要经过这样一条链路:
技术图片

  1. client-->connecter
  2. connector-->transfer
  3. transfer-->connector
  4. connector-->client

在这整个链路中的每个环节都有可能出问题,虽然tcp协议是可靠的,但是它只能保证链路层的可靠,无法保证应用层的可靠。

例如在第一步中,connector收到了从client发出的消息,但是转发给transfer失败,那么这条消息Bob就无法收到,而Alice也不会意识到消息发送失败了。

如果Bob状态是离线,那么消息链路就是:

  1. client-->connector
  2. connector-->transfer
  3. transfer-->mq

如果在第三步中,transfer收到了来自connector的消息,但是离线消息入库失败,
那么这个消息也是传递失败了。
为了保证应用层的可靠,我们必须要有一个ack机制,使发送方能够确认对方收到了这条消息。

具体的实现,我们模仿tcp协议做一个应用层的ack机制。

tcp的报文是以字节(byte)为单位的,而我们以message单位。
技术图片
发送方每次发送一个消息,就要等待对方的ack回应,在ack确认消息中应该带有收到的id以便发送方识别。

其次,发送方需要维护一个等待ack的队列。 每次发送一个消息之后,就将消息和一个计时器入队。

另外存在一个线程一直轮询队列,如果有超时未收到ack的,就取出消息重发。

超时未收到ack的消息有两种处理方式:

  1. 和tcp一样不断发送直到收到ack为止。
  2. 设定一个最大重试次数,超过这个次数还没收到ack,就使用失败机制处理,节约资源。例如如果是connector长时间未收到client的ack,那么可以主动断开和客户端的连接,剩下未发送的消息就作为离线消息入库,客户端断连后尝试重连服务器即可。

不重复、不乱序

有的时候因为网络原因可能导致ack收到较慢,发送方就会重复发送,那么接收方必须有一个去重机制。
去重的方式是给每个消息增加一个唯一id。这个唯一id并不一定是全局的,只需要在一个会话中唯一即可。例如某两个人的会话,或者某一个群。如果网络断连了,重新连接后,就是新的会话了,id会重新从0开始。

接收方需要在当前会话中维护收到的最后一个消息的id,叫做lastId
每次收到一个新消息, 就将id与lastId作比较看是否连续,如果不连续,就放入一个暂存队列 queue中稍后处理。

例如:

  • 当前会话的lastId=1,接着服务器收到了消息msg(id=2),可以判断收到的消息是连续的,就处理消息,将lastId修改为2。

  • 但是如果服务器收到消息msg(id=3),就说明消息乱序到达了,那么就将这个消息入队,等待lastId变为2后,(即服务器收到消息msg(id=2)并处理完了),再取出这个消息处理。

因此,判断消息是否重复只需要判断msgId>lastId && !queue.contains(msgId)即可。如果收到重复的消息,可以判断是ack未送达,就再发送一次ack。

接收方收到消息后完整的处理流程如下:
技术图片

伪代码如下:

class ProcessMsgNode
    /**
     * 接收到的消息
     */
    private Message message;
    /**
     * 处理消息的方法
     */
    private Consumer<Message> consumer;


public CompletableFuture<Void> offer(Long id,Message     message,Consumer<Message> consumer) 
    if (isRepeat(id)) 
    //消息重复
        sendAck(id);
        return null;
    
    if (!isConsist(id)) 
    //消息不连续
        notConsistMsgMap.put(id, new ProcessMsgNode(message, consumer));
        return null;
    
    //处理消息
    return process(id, message, consumer);


private CompletableFuture<Void> process(Long id, Message message, Consumer<Message> consumer) 
    return CompletableFuture
        .runAsync(() -> consumer.accept(message))
        .thenAccept(v -> sendAck(id))
        .thenAccept(v -> lastId.set(id))
        .thenComposeAsync(v -> 
            Long nextId = nextId(id);
            if (notConsistMsgMap.containsKey(nextId)) 
                //队列中有下个消息
                ProcessMsgNode node = notConsistMsgMap.get(nextId);
                return process(nextId, node.getMessage(), consumer);
             else 
                //队列中没有下个消息
                CompletableFuture<Void> future = new CompletableFuture<>();
                future.complete(null);
                return future;
            
        )
        .exceptionally(e -> 
            logger.error("[process received msg] has error", e);
            return null;
        );

安全性

无论是聊天记录还是离线消息,肯定都会在服务端存储备份,那么消息的安全性,保护客户的隐私也至关重要。
因此所有的消息都必须要加密处理。
在存储模块里,维护用户信息和关系链有两张基础表,分别是im_user用户表和im_relation关系链表。

  • im_user表用于存放用户常规信息,例如用户名密码等,结构比较简单。
  • im_relation表用于记录好友关系,结构如下:
CREATE TABLE `im_relation` (
  `id` bigint(20) COMMENT '关系id',
  `user_id1` varchar(100) COMMENT '用户1id',
  `user_id2` varchar(100) COMMENT '用户2id',
  `encrypt_key` char(33) COMMENT 'aes密钥',
  `gmt_create` timestamp DEFAULT CURRENT_TIMESTAMP,
  `gmt_update` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
  PRIMARY KEY (`id`),
  UNIQUE KEY `USERID1_USERID2` (`user_id1`,`user_id2`)
);
  • user_id1user_id2是互为好友的用户id,为了避免重复,存储时按照user_id1<user_id2的顺序存,并且加上联合索引。
  • encrypt_key是随机生成的密钥。当客户端登录时,就会从数据库中获取该用户的所有的relation,存在内存中,以便后续加密解密。
  • 当客户端给某个好友发送消息时,取出内存中该关系的密钥,加密后发送。同样,当收到一条消息时,取出相应的密钥解密。

客户端完整登录流程如下:
技术图片

  1. client调用rest接口登录。
  2. client调用rest接口获取该用户所有relation
  3. client向connector发送greet消息,通知上线。
  4. connector拉取离线消息推送给client。
  5. connector更新用户session。

那为什么connector要先推送离线消息再更新session呢?我们思考一下如果顺序倒过来会发生什么:

  1. 用户Alice登录服务器
  2. connector更新session
  3. 推送离线消息
  4. 此时Bob发送了一条消息给Alice

如果离线消息还在推送的过程中,Bob发送了新消息给Alice,服务器获取到Alice的session,就会立刻推送。这时新消息就有可能夹在一堆离线消息当中推过去了,那这时,Alice收到的消息就乱序了。

而我们必须保证离线消息的顺序在新消息之前。

那么如果先推送离线消息,之后才更新session。在离线消息推送的过程中,Alice的状态就是“未上线”,这时Bob新发送的消息只会入库im_offlineim_offline表中的数据被读完之后才会“上线”开始接受新消息。这也就避免了乱序。

存储设计

存储离线消息

当用户不在线时,离线消息必然要存储在服务端,等待用户上线再推送。理解了上一个小节后,离线消息的存储就非常容易了。增加一张离线消息表im_offline,表结构如下:

CREATE TABLE `im_offline` (
  `id` int(11) COMMENT '主键',
  `msg_id` bigint(20) COMMENT '消息id',
  `msg_type` int(2) COMMENT '消息类型',
  `content` varbinary(5000) COMMENT '消息内容',
  `to_user_id` varchar(100) COMMENT '收件人id',
  `has_read` tinyint(1) COMMENT '是否阅读',
  `gmt_create` timestamp COMMENT '创建时间',
  PRIMARY KEY (`id`)
);

msg_type用于区分消息类型(chat,ack),content加密后的消息内容以byte数组的形式存储。
用户上线时按照条件to_user_id=用户id拉取记录即可。

防止离线消息重复推送

我们思考一下多端登录的情况,Alice有两台设备同时登陆,在这种并发的情况下,我们就需要某种机制来保证离线消息只被读取一次。

这里利用CAS机制来实现:

  1. 首先取出所有has_read=false的字段。
  2. 检查每条消息的has_read值是否为false,如果是,则改为true。这是原子操作。
update im_offline set has_read = true where id = $msg_id and has_read = false
  1. 修改成功则推送,失败则不推送。

相信到这里,同学们已经可以自己动手搭建一个完整可用的IM服务端了。更多问题欢迎评论区留言~~

IM1.0.0版本已上线,github链接:
https://github.com/yuanrw/IM
觉得对你有帮助请点个star吧~!

技术图片

以上是关于C#服务端,Android客户端 开发IM,服务端怎么弄,有没有开源的框架的主要内容,如果未能解决你的问题,请参考以下文章

C#服务器端接收并解析android客户端传过来的json数据

从零开始开发IM(即时通讯)服务端

如何在Android系统下开发一个聊天软件?

从零开始开发IM(即时通讯)服务端

如何来实现IM?~webScoket 服务端开发

C#使用UDP协议开发服务端遇到的问题~~