套用GGTalk做项目的经验总结——GGTalk源码详解系列(一)
坦白讲,我们公司其实没啥技术实力,之所以还能不断接到各种项目,全凭我们老板神通广大!要知道他每次的饭局上可都是些什么人物!
但是项目接下一大把,就凭咱哥儿几个的水平,想要独立自主、保质保量保期地一个个做出来,那也是有点难以置信。之前咱也跟老板反映过这个困难,建议他再召两个高手过来。不过领导虽然书读的不多,有一句古训倒是背得特别熟——“君子生非异也,善假于物也”。所以咱们公司一直奉行拿来主义。
园子里的这个GGTalk——C#开源即时通讯系统,咱们前前后后用它移花接木做的IM项目也不下三四个了。初次入手的时候,洋洋代码,多少感觉有些难以把握。不过一来二去,理清了头绪,也就一览无余了。
相信跟我们一样想要利用GGTalk的同学大有人在,于是我打算写这样一个《GGTalk——C#开源即时通讯系统源码介绍系列》,把自己对GGTalk的梳理分享给大家,让大家更容易上手。
那接下来我们就言归正传。
一.GGTalk的宏观结构
如图,GGTalk中有4个项目,第一个“GGTalk”是客户端项目;“GGTalk.Core”是客户端和服务端共用的一些类,主要包括一些数据实体,还有一些通信协议类;“GGTalk.Server”是服务端项目;“JustLib”是作者封装的一些常用类和控件。
二.GGTalk是如何实现注册的?
GGTalk采用Remoting技术来完成注册。
1.先定义接口
namespace GGTalk
{
/// <summary>
/// 用于提供注册服务的Remoting接口。
/// </summary>
public interface IRemotingService :IChatRecordPersister
{
RegisterResult Register(GGUser user); /// <summary>
/// 根据ID或Name搜索用户【完全匹配】。
/// </summary>
List<GGUser> SearchUser(string idOrName); /// <summary>
/// 发送系统通知给所有在线用户。
/// </summary>
void SendSystemNotify(string title, string content);
}
}
2.服务端接口实现
namespace GGTalk.Server
{
internal class RemotingService :MarshalByRefObject, IRemotingService
{
private GlobalCache globalCache;
private IRapidServerEngine rapidServerEngine;
public RemotingService(GlobalCache db ,IRapidServerEngine engine)
{
this.globalCache = db;
this.rapidServerEngine = engine;
} public RegisterResult Register(GGUser user)
{
try
{
if (this.globalCache.IsUserExist(user.UserID))
{
return RegisterResult.Existed;
}
this.globalCache.InsertUser(user);
return RegisterResult.Succeed;
}
catch (Exception ee)
{
return RegisterResult.Error;
}
} public List<GGUser> SearchUser(string idOrName)
{
return this.globalCache.SearchUser(idOrName);
} public override object InitializeLifetimeService()
{
return null;
}
}
}
3.服务端发布服务
#region 发布用于注册的Remoting服务
RemotingConfiguration.Configure("GGTalk.Server.exe.config", false);
RemotingService registerService = new Server.RemotingService(globalCache ,Program.RapidServerEngine);
RemotingServices.Marshal(registerService, "RemotingService");
#endregion
服务端配置文件:
<system.runtime.remoting>
<application>
<channels>
<!--用户注册Remoting服务端口-->
<channel ref="tcp" port="4500" >
<serverProviders>
<provider ref="wsdl" />
<formatter ref="soap" typeFilterLevel="Full" />
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
4.客户端订阅服务
int registerPort = int.Parse(ConfigurationManager.AppSettings["RemotingPort"]);
this.remotingService = (IRemotingService)Activator.GetObject(typeof(IRemotingService), string.Format("tcp://{0}:{1}/RemotingService", ConfigurationManager.AppSettings["ServerIP"], registerPort)); ;
三.总结Remoting技术
1.Remoting使用中的三要素:
1.一个可远程处理的对象。
2.一个服务端应用程序域用(也叫宿主应用程序域中),于侦听针对该对象的请求。
3.一个客户端应用程序域,用于发出针对该对象的请求。
2.代理:
代理是一个提供了和真实对象完全一样的接口、公共方法、属性等成员的对象。在运行过程中,.NET Remoting基于对象元数据生成代理。代理只提供接口,不提供对象的状态,因为对象的真正状态在宿主应用程序域中存储。代理在这里只转发调用。转发调用到一个对象叫封送处理。封送处理的目标是让客户端调用服务端时感觉不到是在与远端对象交流,而是与本地对象在交流。如果通过代理来访问对象,该对象必需是从 MarshalByRefObject抽象类派生。
3.Remoting架构:
四.知识点拓展
1. 用应用程序域
操作系统和运行库环境通常会在应用程序间提供某种形式的隔离。例如,Microsoft Windows 使用进程来隔离应用程序。为确保在一个应用程序中运行的代码不会对其他不相关的应用程序产生不良影响,这种隔离是必需的。
2.用应用程序域优点
在一个应用程序中出现的错误不会影响其他应用程序。因为类型安全的代码不会导致内存错误,所以使用应用程序域可以确保在一个域中运行的代码不会影响进程中的其他应用程序。
能够在不停止整个进程的情况下停止单个应用程序。使用应用程序域使您可以卸载在单个应用程序中运行的代码。
在一个应用程序中运行的代码不能直接访问其他应用程序中的代码或资源。为了强制实施此隔离,公共语言运行库禁止在不同应用程序域中的对象之间进行直接调用。要在各域之间传递对象,可以复制这些对象,或通过代理访问这些对象。如果复制对象,那么对该对象的调用为本地调用。也就是说,调用方和被引用的对象位于同一应用程序域中。如果通过代理访问对象,那么对该对象的调用为远程调用。在此情况下,调用方和被引用的对象位于不同的应用程序域中。域间调用所采用的远程调用基础结构与两个进程间的调用或两台计算机间的调用的基础结构相同。因此,被引用的对象的元数据必须对于两个应用程序域均可用,以便用 JIT 正确编译该方法调用。如果调用域对被调用对象的元数据没有访问权,则编译可能失败,并引发类型为 System.IO.FileNotFound 的异常。
代码行为的作用范围由它运行所在的应用程序决定。换言之,应用程序域将提供应用程序版本策略等配置设置、它所访问的任意远程程序集的位置,以及加载到该域中的程序集的位置信息。
向代码授予的权限可以由代码运行所在的应用程序域来控制。
五.后记
这是该系列的第一篇,一篇博客篇幅有限,能讲清楚一两个问题已经很不错。要想把GGTalk——C#开源即时通讯系统全部讲透,恐怕得要上百篇博客才够。首先要感谢GGTalk的作者,能够开发出这样优秀的C#开源即时通讯系统,而且无私的开源出来。其次,希望我做的工作也能给大家带来收获,一方面可以方便大家利用GGTalk,另一方面也为学习GGTalk的同学提供一个参考,希望大家可以从中汲取营养,不仅仅是复用这些代码,也能够从中学到蕴含着的知识与技术。
解读GGTalk,这个工作很辛苦,希望大家鼓励,也希望更多的朋友参与其中!
套用GGTalk做项目的经验总结——GGTalk源码详解系列(一)的更多相关文章
- Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码)
Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码) 备注: 之前在Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合中 ...
- [转]3天搞定的小型B/S内部管理类软件定制开发项目【软件开发实战10步骤详解】
本文转自:http://www.cnblogs.com/jirigala/archive/2010/10/07/1845275.html 2010-10-07 21:39 by 通用C#系统架构, 5 ...
- 做个简单的Redis监控(源码分享)
Redis监控 Redis 是目前应用广泛的NoSQL,我做的项目中大部分都是与Redis打交道,发现身边的朋友也更多人在用,相对于memcached 来说,它的优势也确实是可圈可点.在随着业务,数据 ...
- Git学习系列之如何正确且高效地将本地项目上传到Github(图文详解)
不多说,直接上干货! 首先你需要一个Github账号,所以还没有的话先去注册吧! https://github.com/ 见 如何走上更高平台分享传递干货知识:(开通个人Github面向开源及私有软件 ...
- 如何在IDEA里给大数据项目导入该项目的相关源码(博主推荐)(类似eclipse里同一个workspace下单个子项目存在)(图文详解)
不多说,直接上干货! 如果在一个界面里,可以是单个项目 注意:本文是以gradle项目的方式来做的! 如何在IDEA里正确导入从Github上下载的Gradle项目(含相关源码)(博主推荐)(图文详解 ...
- 做个简单的Redis监控(源码分享)[转载]
Redis监控 Redis 是目前应用广泛的NoSQL,我做的项目中大部分都是与Redis打交道,发现身边的朋友也更多人在用,相对于memcached 来说,它的优势也确实是可圈可点.在随着业务,数据 ...
- python接口自动化(四十二)- 项目结构设计之大结局(超详解)
简介 这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块---模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子.并且有很多小伙伴对于接口项目测试的框架 ...
- 百度ueditor vue项目应用 -- 图片上传源码修改
本文目的有两个,一.废掉单图上传,二.改造多图上传 大家都知道百度ueditor不是针对vue项目开发的,官方文档提供的源码包里有需要后端配置的接口,but到vue项目就不太好办了,网上有些文章也介绍 ...
- 从零搭建vue3.0项目架构(附带代码、步骤详解)
前言: GitHub上我开源了vue-cli.vue-cli3两个库,文章末尾会附上GitHub仓库地址.这次把2.0的重新写了一遍,优化了一下.然后按照2.0的功能和代码,按照vue3.0的语法,完 ...
随机推荐
- Hadoop自定义分组Group
matadata: hadoop a spark a hive a hbase a tachyon a storm a redis a 自定义分组 import org.apache.hadoop.c ...
- SQL中CHARINDEX()/INSTR()函数和SUBSTRING()/SUBSTR()函数
一.SQLServer中的CHARINDEX() 和ORACLE中的INSTR()函数 1.INSTR(C1,C2[,I[,J]]) [功能]在一个字符串中搜索指定的字符,返回发现指定的字符的位置; ...
- spring mvc基础配置
web.xml 配置: <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> ...
- 编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试Stud
package zuoye; public class student { int age; String name; int stuNO; void outPut() { System.out.pr ...
- Swift内存管理、weak和unowned以及两者区别
Swift 是自动管理内存的,这也就是说,我们不再需要操心内存的申请和分配.当我们通过初始化创建一个对象时,Swift 会替我们管理和分配内存.而释放的原则遵循了自动引用计数 (ARC) 的规则:当一 ...
- 不错的flash,动漫,小插件小集
(来源:http://abowman.com/google-modules/) embed code <object width="220" height="166 ...
- JAVA 基本运算符(摘)
(搞自:Java经典入门教程) http://wenku.baidu.com/link?url=IoWI58cD5vzeHN-NL4pN7Gren-RfzydrhjDlETAByC9L-9ANinyL ...
- [译] 企业级 OpenStack 的六大需求(第 3 部分):弹性架构、全球交付
全文包括三部分: 第一部分:API 高可用和管理以及安全模型 第二部分:开放架构和混合云兼容 第三部分:弹性架构和全球交付 需求 5 - 扩展.弹性和性能 企业级的内容很丰富.过去,企业级往往和高可靠 ...
- [转]Using Entity Framework (EF) Code-First Migrations in nopCommerce for Fast Customizations
本文转自:https://www.pronopcommerce.com/using-entity-framework-ef-code-first-migrations-in-nopcommerce-f ...
- 关于TP3.2微信开发那点事(基础篇)
许久没有为博客更新内容,今天我将过去一周做的微信服务号的相关心得体会在此分享,具体如何申请成为服务号的相关流程文档都有,可根据要求完成: 开发第一步:开发前配置: AppID-->微信号的&qu ...