1. 设备更新,主动推送模式更好,不仅效率高(否则客户端要开线程定时查询),而且容易扩展。当消息需要经过很多查询流程的时候更为明显,如果一个查询经过很多服务器(处理者)才送到真正要查询的设备接入服务器,那么如果查询的人很多,不仅网络流量大,而且设备接入服务器负担大(所有查询都要亲自处理)。如果做成主动推送(订阅者)模式,那么,当设备有变化的时候,经过服务器,推送到客户端(查询者)直接打交道的服务器(中心),那么中心就相当于(视频的转发服务器)一个缓存,可以直接回应客户端的查询,同样中心也可以做成功主动推送的模式,当设备信息有变化的时候,主动推送给客户端。(本质上是指责的转移,一些需要客户端询问的在应答的消息,直接有需要的消息时候发送给客户端,不需要客户端询问)。
2.一个需要对接的系统(需要很多子系统对接),设计上主站(中心),应该尽可能去处理更多的职责,这样子系统(很多)可以处理的尽量简单,可靠性也更高。例如告警的上报,主站完全可以不需要,主站完全可以根据数据来判断是否有告警的产生。
3.复杂系统设计上,中介者模式比较常见,可以使得各个子系统之间的依赖尽量少,大多数处理都直接发给中心(中介者),而中心并不处理所有的业务,中心很多时候是对请求的分发。
4.中心的可扩展性:并不是所有的协议中心都要认识,中心订阅分发,订阅只需要一个协议号,当有对应协议时候,中心不知道怎么处理(也不需要),直接把得到的消息转发给订阅者。
5.对于命令模式,处理不一定都是耗时的工作,命令模式的目的只是把命令发送者和处理者分开,一来可以解耦,二来可以传递。如果命令的处理是耗时的操作,才会有命令池,有线程去处理。
6. C++中也有Inner class,通用的做法是在Inner class中把包含自己的类变成友员类,这样,这个inner class就只能这个包含它的类来使用调度了,这样就满足了最少知道原则。其实如果这样的话,通常我们会直接把这个inner class变成包含类的变量与方法,封装成类,好处就是面向对象了,可读性可维护性增强了。在对类增加方法或一些业务功能的时候,这种方法最为常用。
7. 对于public这个关键字,不是在类中把所有的public函数都弄在一起,然后写一个public,对于成员函数较多的情况,完全可以几个相关函数有一个修饰词,例如构造与析构,写一个public,一个接口的方法在写一个public,这样就会整齐容易读了。
8.修改以前代码,如果要增加代码最好也加上// 20100919 xxx add 在最后增加后// 20100919 xxx add finish
9.一行代码不要写长,如果超出,用斜杠\可以换行
10.这个类写成模板类,为了扩展,在服务类“CTransmitService”的cpp文件中的开始地方添加 static CServiceAutoRegistry<CTransmitService> s_sevice这个类,可以在编译期间声明一个具体类CServiceAutoRegistry,并且定义一个类s_sevice,而这个类在定义的同时构造函数中就添加了一个具体的服务。这个的好处是可以扩展,在增加服务的时候不用改变CServiceManager中的方法,否则在初始化函数中就要new 很多对象,例如下面这样。
int CServiceManager::InitModule()
{
///添加功能模块
CIService *pIService= new CControlService();
m_IServiceList.push_back(pIService);
pIService= new CVideoService();
m_IServiceList.push_back(pIService);
pIService= new CSystemService();
m_IServiceList.push_back(pIService);
}
template<class IService>
class CServiceAutoRegistry
{
public:
CServiceAutoRegistry()
{
CServiceManager::Instance()->AddService(new IService);
}
};
也可以在服务类中CTransmitService的构造函数中使用CServiceManager::Instance()->AddService(this);但是如果这样写就要在程序的某个地方调用下CTransmitService的构造函数,在哪里调用还是个问题,所以,像上面的方法,直接在cpp文件中定义一个静态的类的变量是最好的办法。这里也用到了一个技巧就是在定义类对象的时候会自动调用类的构造函数,否则在cpp文件中不能让程序去刻意执行某一个函数。
11. 订阅首先是业务服务器订阅,在业务服务器中,对于特殊的插件还要向tcp模块订阅。中心分发消息的时候只知道分发到哪个服务器dev,服务器的tcp模块在分发到对应的对象还是插件订阅
12. 单例有时候也是需要加锁的,如果单例被多个线程使用。
13. CPublisher类是一个接口实现类,更像一个外观,把需要几个类实现的功能在CPublisher里面用别的类实现了,CPublisher类里面没有任何的逻辑代码,全是借助别的类,实现接口的功能。
14. 中心对于收到的告警通知和设备异常分发的时候是不需要Response的,其他所有的消息时需要回应的,即使不需要回应,在转发时候生成的transferResponse中的OnTimeout超时后也不会有特别提示,只是效率欠佳。透传是全部需要回应的,只要调用TransferNetMsg方法都会生成异步的Response,OnRespons的时候都会直接通过Response中保存的handle转发。
15. 协议的订阅是在业务服务器启动时候集中订阅的,插件服务是业务服务器的核心服务,使用插件的时候一般都在一个继承自CSvcPluginServiceBase的类的方法InitPluginService中调用一个m_Server的启动,这个server启动的时候框架会调用其中的start方法,start方法中有对协议的订阅,统一订阅到一个CRegNetMsgService类中,然后业务服务器模块启动最后会使用CRegNetMsgService给中心发送一条订阅协议。
16. 因为类的非静态成员函数没有this指针,而回调函数一般参数都规定好,没有传入this指针的地方,回调函数也就没有方法获得this指针,就没法访问非静态成员函数。想在回调函数中调用类的成员函数可以定义一个静态的指针,让后在类的构造函数中把this指针赋值给静态指针,在静态函数中使用指针访问成员函数。http://www.cnblogs.com/schoolers/archive/2012/03/28/2421052.html
17. ACE的常用方法,显示信息
/// Dump the state of an object.
void dump (void) const;
18. system_common一定在ISocketOwner前面
19. 如果只是调用一个类对象,那么没有必要使用模板,当要new对象时候,和对对象操作的时候可以使用模板。
20. /// 串口通信没有区分监听、还是已连接套接字
/// 物理上的两个串口连接起来后,双方就可以读写了
/// 串口为独占式的,只能被connect一次
/// 所以异步Proactor的模式即使使用意义也不大
/// 异步处理,是为了提高并发连接时提高性能,而每个串口只有一个连接