QSocket 总体设计框架说明(观赏)
QSocket 是 QDAC 开源组件的一个重要的组成部分,终于要开始开工了,为了方便大家了解 QSocket,对 QSocket 的总体设计的一些想法,我在这里给大家简要的描述一下。
首先,QSocket 同 QDAC 的其它组成部分一样,是跨平台的,这意味着你可以在不同的操作系统中,体验 QSocket 为你带来的良好体验。
其次,QSocket 是 Delphi 的原生代码,所以不会依赖于其它第三方库(QDAC 自身的不算:-:)。
其三,QSocket 会基于各个操作系统自身,进行针对性的优化,换句话说,IOCP/KQueue/EPOLL 都将在里面看到它的身影。
老末,QSocket 将是一个基于异步的 IO 框架,虽然会有一些同步的方法,不过异步是核心,同步是封装而已。
好了,现在进入总体的框架描述部分。
QSocket 的设计理念中包含以下几个部分:
- IQTransport
Transport,顾名思议就是一个传输港。它来负责将数据传送到目标,这里目标包括两个含义:
首先是发送到目标,则 IQTransport 负责将数据传递给目标地址。但具体是否传送成功,取决于 Transport 所使用的协议及实现;
其次是接收后派发到目标,则 IQTransport 负责将接收到的数据,传递给具体的处理函数,来完成对数据的处理。
通俗点讲,IQTransport 就是一个港口,负责货物的打包、装运和分流,为此它提供了:- 用于指定本地要监听的地址及端口的 Bindings 列表,也可以通过简单的指定 LocalPort 来在所有地址的指定端口上监听通讯(仅对TCP/UDP有效,其它协议该属性可能无意义);
- 用于管理已经建立的连接的 Connections 列表;
- 用于广播数据的 Broadcast 函数;
- 用于对要传送的数据进行打包操作的编码处理器 Codecs;
- 用于确定要将接收到的数据如果处理的派发器列表 Dispatchers;
- 其它由 IQTransport 的接口实现提供的其它属性及方法
- IQRequest
Request,请求。在 QSocket 中,一次请求+回应构成一个请求。比如,我们向服务器端发送一个命令,此时就会生成一个请求,服务器返回处理结果,这个请求的处理就结束了。我们再向服务器发送后续的命令,就是新的请求了。有一个概念需要大家明白,请求未必有回应,所以有求必应在 QSocket 中并不是一个必然的概念。由于请求的发送及处理都需要时间,如果此处用同步等待的方法来编程,很明显会降低整个系统的效率,所以,IQRequest 的接口实现了异步发送接口。IQRequest 提供的主要内容如下:- 请求 ID,一个无符号32位整数,它具体的意义,取决于具体的实现,一般用它来标记一次唯一的请求和其对应的回复;
- 优先级 Priority,一个枚举类型,用于指定请求发送的优先级。如果你同时投递了几个请求,则优先级高的请求将会优先发送。但是,这个也取决于具体的实现。QSocket 本身会提供一个自己封装的多会话并行发送协议,它允许在现有会话发送过程中插入高优先级的会话发送,以避免低优先级的长时间数据传输请求影响普通或紧急业务数据的传送。不过这需要服务器端也要兼容 QSocket 的这个协议。在一般的场景实现中,阿门,忽略它吧,很少有协议支持它。
- 关联的连接对象 Connection,这个不用说啥了。
- 记录请求内容的 RequestData,在接收到请求后,要处理的数据都在里面了。
- 记录回应内容的 ReplyData,在接到回应后,需要处理的数据都在里面了。
- 错误代码 ErrorCode 和错误提示 ErrorMsg,这个就没啥可说的了。
- 发送请求的函数 PostRequest 和 SendRequest,一个是异步,一个是同步。异步的需要提供一个回调函数,以便在得到结果时响应,如果不提供,则意味着忽略返回结果的处理。
- 发送回应的函数 PostReply。
- IQConnection
Connection,连接,这个搞网络编程的都明白是啥,就不多说。需要注意一点,在 QSocket 中,UDP 协议也是有连接的,只不过这种连接是有限制的:
首先,由于 UDP 协议本身是无连接的,超过一段时间未收发数据,会被网关给断掉,所以这个连接本身会内置一些辅助的连接保持功能(如无数据,每隔10秒会发送一个无载荷的空 UDP 数据包,以保持网关会话的有效性)。
其次,UDP 协议本身是不保证数据的准确到达的,所以基于 UDP 的连接本身同样也不保证这一点。但 QSocket 会提供更高一级别的封装,来保证 UDP 协议达到类似于 TCP 的有连接效果,同样,这种封装协议的代价就是服务器端也需要采用同样的协议。
IQConnection 提供的主要内容如下:- 本地绑定的地址 LocalAddr;
- 远程绑定的地址 RemoteAddr;
- 创建一个新请求的函数 NewRequest;
- 发送和接收数据的接口:Post/Send/Recv/Peek。
- IQDataCodec
Data Codec ,数据编码和解码接口。主要用于数据的加密、压缩以及其它打包的处理工作。一次传输过程,可能要经过多个 IQDataCodec 进行流水线处理,所以它的工作是否正常,严重依赖于发送和接收端的设置是否一致,包括顺序。比如,我们先压缩后加密和先加密,后压缩就是两个不同的选择。编码的过程,是按照 IQDataCodec 的添加顺序进行的,解码的过程,则是按照添加顺序的逆序执行的。
IQDataCodec 提供的主要内容如下:- 编码函数 Encode
- 解码函数 Decode
- 编解码器名称 Name
- IQCommand
Command,命令。它的主要作用是配合 IQCommandDispatcher,管理支持的请求命令的处理函数。一般来说,一个命令只应该有一个处理函数,不过 QSocket 支持一个命令交由多个函数来处理,它会在接收到请求后,传递给第一个处理函数,如果第一个处理函数未设置 AHandled 参数为 true,则会交给第二个函数处理,直到所有的处理函数都调用完成或者 AHandled 在某个处理函数中返回了 true,才会中止处理。这主要是方便一些通知类型的命令的处理。
IQCommand 提供的主要内容如下:- 命令 Id,是否有意义取决于具体的协议,这一般用于基于数值命令驱动的处理
- 命令路径 NamePath,这一般用于字符类命令驱动的协议的处理
- 命令响应列表的管理函数及属性:Add/Delete/Remove/Clear/Count/Handlers
- 命令处理函数 HandleCommand
- IQCommandDispatcher
Command Dispatcher,命令调度器。它负责将接收的请求中的内容进行解码,取出其中的命令,然后查找注册的 IQCommand,并调用相应的 IQCommand 的 HandleCommand 方法进行实际的处理。
IQCommandDispatcher 提供的主要内容如下:- 命令注册及管理函数、属性:Add/Delete/Remove/Clear/ByNamePath/ById/Count/Commands
- 判断是否能够派发指定的数据内容的函数:CanDispatch
- 执行实际派发的函数:Dispatch
- IQDataBuffer
Data Buffer,数据缓冲区实现。它支持四种不同的缓冲区,以便根据实际需要来创建不同类型的缓冲区(关于它实现的主要内容省略):- 内存缓冲区,直接使用 NewBuffer 就可以创建一个内在缓冲区对象;
- 文件缓冲区,直接使用 NewBuffer ,将要保存缓冲内容的文件名当做参数传递,就可以创建一个文件缓冲对象。这适用于文件或大型的数据请求的处理。
- 流缓冲区,直接使用 NewBuffer,将一个 TStream 类型的对象传递进去做为参数,就可以创建一个流缓冲对象,文件缓冲区实际上也是基于它实现的。
- 共享缓冲区,直接使用 ShareBuffer 函数,将一个已有的缓冲区接口做为参数传入,就可以创建一个共享的流缓冲对象,通过 ShareBuffer 返回的 IQDataBuffer 可以独立使用,共同访问同一个源 IQDataBuffer 的数据。通过 ShareBuffer 访问源数据的内容是线程安全的。
- IQSocketFactory
Factory,就是工厂了。这个工厂是一个不负责任的工厂,只负责生产出 Transport 和 Connection 对象,不负责售后。它的主要目的是简化上层的各种东西的创建,如果我们要创建一个面向Tcp 连接,则我们可以调用 SocketFactory.NewCo6nnection(‘tcp://connection’) 得到一个 TCP 连接对象,或者我们直接调用 SocketFactory.NewConnection(‘tcp://connection?dst=192.168.0.1:980’) 来创建一个连接到 192.160.0.1 的 980 端口的连接对象。
IQSocketFactory 生产以下内容:- IQTransport,URI 的 host 部分为 transport,Scheme 部分则由相应的 IQTransport 实现自己约定。
- IQConnection,URI 的 host 部分为 connection,Scheme 部分同样由相应的 IQConnection 实现自己约定。
- IQDataBuffer,URI 的 host 部分为 buffer,scheme 包括:mem/file 两种,不支持流缓冲区和共享缓冲区
- IQCommandDispatcher,URI 的 host 部分为 dispatcher,Scheme 部分同样由相应的 IQCommandDispatcher 实现自己约定。
- IQRequest,URI 的 host 部分为 request,一般更推荐调用 IQConnection 的 NewRequest 来实现。Scheme 部分同样由相应的 IQRequest 实现自己约定。
- TQAddr
Addr(ess),地址的归一化封装。在 QSocket 中,各种协议的不同地址表达形式,都通过 TQAddr 进行封装。它支持IPv4/IPv6/UnixDomain/NamePipe/FilePath类型的地址管理,主要提供的内容如下:- 类型转换重载 Implicit,实现将 IPv4/IPv6 地址直接转换为相应的 TQAddr 结构
- 生成相应类型的 TQAddr 结构的辅助函数:MakeIPv4/MakeIPv6/MakeAddr
- 生成 IPv4/IPv6 协议对应接口类型的 ToIPAddr
- 地址类型属性:AddrType
- 完整地址文本表示:Text
- 仅地址的文本表示:AddrOnly
- 端口号:Port
- 其它属性:AsIPv4/AsIPv6
上述这些部分构成了 QSocket 的核心,后面更复杂的是实现上面说的这一堆东西。其中,TQAddr 和 IQDataBuffer 的接口已经实现完成,但 QSocket 的万里长征,这才是第一步,希望在开发和测试过程中,大家都多多参与。
附:QSocket 通讯过程示意图


http://blog.qdac.cc/?p=4408
QSocket 总体设计框架说明(观赏)的更多相关文章
- JAVA车票管理系统(简单GUI)
一. 需求分析 1.设计题目:车票管理系统 用JAVA语言和数据结构知识设计设计车票管理系统.要求如下所述: 一车站每天有n个发车班次,每个班次都有一个班次号(1.2.3…n),固定的发车时间, ...
- GIS在水利中的应用
摘要 GIS具有数据存储.查询.统计.图形显示.分析.模拟.决策和预测等功能,在水利中得到越来越广泛的应用,可谓水利现代化的“火车头”. 关键词 GIS 水利 应用 地理信息系统GIS通常泛指用于获 ...
- leveldb 源码--总体架构分析
一 本文目的 对leveldb的总体设计框架分析(关于leveldb基本原理,此文不做阐述,读者可以自行检索文章阅读即可),对leveldb中底层数据存储数据格式,内存数据模型,compact,版本管 ...
- Dubbo源码学习总结系列三 dubbo-cluster集群模块
Dubbo集群模块的目的是将集群Invokers构造一个透明的Invoker对象,其中包含了容错机制.负载均衡.目录服务(服务地址集合).路由机制等,为RPC层提供高可用.高并发.自动发现.可治理的S ...
- 【开源】OSharp框架解说系列(1):总体设计及系列导航
系列文章导航 [开源]OSharp框架解说系列(1):总体设计 [开源]OSharp框架解说系列(2.1):EasyUI的后台界面搭建及极致重构 [开源]OSharp框架解说系列(2.2):EasyU ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计
目 录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章 框架总体的设计... 2 2.1 ...
- 基于C/S架构的3D对战网络游戏C++框架_02系统设计(总体设计、概要设计)
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- OSharp框架总体设计
OSharp框架解说系列(1):总体设计 〇.前言 哈,距离前一个系列<MVC实用构架设计>的烂尾篇(2013年9月1日)已经跨了两个年头了,今天是2015年1月9日,日期已经相映,让我们 ...
- 基于MEF的插件框架之总体设计
基于MEF的插件框架之总体设计 1.MEF框架简介 MEF的全称是Managed Extensibility Framework(MEF),其是.net4.0的组成部分,在3.5上也可以使用.熟悉ja ...
随机推荐
- Oracle数据库表空间 数据文件 用户 以及表创建的SQL代码
--create the tablespace CREATE SMALLFILE TABLESPACE "TABLE_CONTAINER" --创建表空间 DATAFILE 'E: ...
- springMvc中restful风格的api路径中把小数点当参数,SpringMvc中url有小数点
在springMvc web项目中restful风格的api路径中有小数点会被过滤后台拿不到最后一个小数点的问题, 有两种解决方案: 1:在api路径中加入:.+ @RequestMapping(&q ...
- ajax——XMLHttpRequest
XMLHttpRequest对象.能够让ajax程序在不又一次载入的页面的情况下更新页面数据,页面载入完毕后从server接受发生数据.这样既减轻了server负担又回顾了响应速度,缩短了用户的等待时 ...
- 单点登录原理与简单实现--good
一.单系统登录机制 1.http无状态协议 web应用采用browser/server架构,http作为通信协议.http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关 ...
- win10 uwp 线程池
原文:win10 uwp 线程池 如果大家有开发 WPF 或以前的程序,大概知道线程池不是 UWP 创造的,实际上在很多技术都用到线程池. 为什么需要线程池,他是什么?如何在 UWP 使用线程池,本文 ...
- .net remoting 抛出异常
原文:.net remoting 抛出异常 本文告诉大家如何在使用 .net remoting 的时候,抛出异常. 所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefOb ...
- 禁止Delphi2010检测新版本
启动Delphi2010后,Delphi2010 总会提示下载更新包,而对于D版用户来说,这个功能可能反而带来麻烦,那么有解决办法吗?答案是肯定的.1. 打开 C:\Documents and Set ...
- Cordova 集成极光推送
1.申请极光推送账号,创建应用,配置包等信息,可以获得AppKey,用于添加Cordova插件,这部分暂不细讲,根据官网的提示操作就能完成. 2.命令窗口给cordova项目添加极光推送插件 cord ...
- Android--在Android应用中愉快地写C/C++代码(转)
1 前言 一直想在android层面写c进程,然后java可以与c进程交互,以前在android源码中想玩就可以直接在init.rc中加上交叉编译好的c进程就可以了,而在ide中,也就是ndk编译后各 ...
- 在嵌入式程序中QT去掉鼠标指针
在像arm的QT编程当中,一般都是使用触摸来操作,当是我们运行程序的时候会发现总是有个鼠标箭头在那里,下面介绍种方法将其给去掉.这样就漂亮多了.在main()函数加入 #include <QWS ...