上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法。当时为了通俗易懂采用了消息异步调用的方式。今天我们要采用消息同步调用的方式来实现,并且对比一下两种方式的优劣。通过这个实例也能让对于“同步调用异步调用”不甚了了的朋友们对于这一对概念有一个初步直观的认识。
  究竟什么是消息同步调用什么是消息异步调用呢?

一·消息异步调用

  对于这个问题我们先不急于从原理上回答,先来看下上一次客户端向服务端发送消息的代码。
        private void button1_Click(object sender, EventArgs e)
{
int leftNum = int.Parse(this.textBox_leftNum.Text);
int rightNum = int.Parse(this.textBox_rightNum.Text);
//将数据转码以备发送给服务端
byte[] leftNumCode = BitConverter.GetBytes(leftNum);
byte[] rightNumCode = BitConverter.GetBytes(rightNum);
byte[] NumbersCode = new byte[];//用来合并待发送的消息(一个整型占4个字节)
for (int i = ; i < ; i++)
{
NumbersCode[i] = leftNumCode[i];//第一个数的编码装进前四位
}
for (int j = ; j < ; j++)
{
NumbersCode[j + ] = rightNumCode[j];//第二个数的编码装进后四位
}
//发送给服务器,100代表做加法这件事
Program.clientEngine.CustomizeOutter.Send(
, NumbersCode);
}

关键是客户端发消息的那句代码,发完消息后客户端就撒手不管了,究竟服务端有没有收到呢?会不会发出去的消息就是“肉包子打狗”呢?客户端不得而知。反正皮球踢给了服务端,好吧服务端接了,然后服务端是这样做的:

 //该方法用来处理客户端通过clientEngine.CustomizeOutter.Send()方法发送过来的消息
public void HandleInformation(string sourceUserID, int informationType, byte[] info)
{
if (informationType == )
{
int leftNum = BitConverter.ToInt32(info, );//将字节数组前四位还原成leftNum
int rigthNum = BitConverter.ToInt32(info, );//将字节数组后四位还原成rigthNum
int result = leftNum + rigthNum;
byte[] resultCode = BitConverter.GetBytes(result);//将计算结果转码
this.serverEngine.CustomizeController.Send(sourceUserID, , resultCode);//发送给对应的客户端
}
}

服务端处理一番后再度发消息给客户端,又一个皮球踢了出去。客户端接球:

 //该方法来处理服务端Send()方法发送过来的消息
public void HandleInformation(string sourceUserID, int informationType, byte[] info)
{
if (informationType == )
{
MessageBox.Show("结果为:" + BitConverter.ToInt32(info, ));
}
}

综上就是消息异步调用,就是发送者只发消息,仅此而已,发完消息该干嘛干嘛,接受者接收消息后再向发送者发消息时,自身角色同时也转换为发送者,按发送者的风格行事。但是从上述过程中可以看出,采用消息异步调用会使得通信过程较为复杂,需要反复“收发”消息。

二·消息同步调用

我们再来看看消息同步调用是怎么做的:

        private void button1_Click(object sender, EventArgs e)
{
int leftNum = int.Parse(this.textBox_leftNum.Text);
int rightNum = int.Parse(this.textBox_rightNum.Text);
//将数据转码以备发送给服务端
byte[] leftNumCode = BitConverter.GetBytes(leftNum);
byte[] rightNumCode = BitConverter.GetBytes(rightNum);
byte[] NumbersCode = new byte[];//用来合并待发送的消息,一个整型占4个字节
for (int i = ; i < ; i++)
{
NumbersCode[i] = leftNumCode[i];//第一个数的编码装进前四位
}
for (int j = ; j < ; j++)
{
NumbersCode[j + ] = rightNumCode[j];//第二个数的编码装进后四位
}
//发送给服务器请求获取结果
byte[] resultCode = Program.clientEngine.CustomizeOutter.Query(, NumbersCode);
int result = BitConverter.ToInt32(resultCode, );//解析
MessageBox.Show("结果为:" + result);
}

重点是发消息语句,与前面的“异步调用”的区别就在于请求返回结果,然而处理过程并不是在客户端的主机上完成的,而是在服务端:

   //该方法用来处理客户端发送过来的请求,即clientEngine.CustomizeOutter.Query()方法发送过来的消息
public byte[] HandleQuery(string sourceUserID, int informationType, byte[] info)
{
if (informationType == )
{
int leftNum = BitConverter.ToInt32(info, );//将字节数组前四位还原成leftNum
int rigthNum = BitConverter.ToInt32(info, );//将字节数组后四位还原成rigthNum
int result = leftNum + rigthNum;
byte[] resultCode = BitConverter.GetBytes(result);//将计算结果转码
return resultCode;
}
return null;
}

表面上类似于调用本地方法,但实质上是一个分布式处理过程。在服务端处理信息的过程中,客户端一直处于等待状态,直到服务端处理完毕返回结果。假使该语句下还有代码块,则在等待过程中不能够执行。这就是消息同步调用。

三·总结

消息同步调用与消息异步调用的概念脱胎于同步调用与异步调用的概念,相当于是对于原概念的拓展。同步调用与异步调用是对于方法的调用而言,所谓同步调用,就是在调用一个方法时,在没有得到结果之前,主调线程处在等待状态;所谓异步调用即,一个方法被调用后,主调线程不用等待结果返回。我们这里所谈的消息同步调用与消息异步调用是针对于“发送/回复”这种通信的逻辑模型而言,能够立即获得回复的发送称为消息同步调用,反之称为消息异步调用。

类似于方法同步调用,消息同步调用也会阻塞当前调用线程,但是由于其模型简单直观,而且将“发送“与”回复”严格匹配,在其适用的场合较消息异步调用模型具有优越性。

毫无疑问,在通信框架中,原始的模型就是异步调用模型,而ESFramework也增加了同步调用的机制,使得编程模型更加丰富。

至于消息同步调用与消息异步调用在实际的项目中如何运用来实现更复杂的需求,完成更强劲的功能,我会在该系列以后的博文中继续探讨,支持的朋友请顶一顶,给与我坚持不懈的力量!

四.源码下载

  让服务器做加法2--同步调用模型

循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用的更多相关文章

  1. 循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天

    <循序渐进做项目系列迷你QQ篇>将陆续介绍客户端聊天,文件传输,加好友,群聊,包括语音聊天,视频聊天,远程桌面等等需求如何实现,感兴趣的朋友可以持续关注.考虑到某些需求较为复杂,本系列采用 ...

  2. 循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)

    一·效果展示 源码派送:MiniQQ1.1 文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天 二·服务端设计 对于实现视频聊天而言,服务端最核心的工作就是要构造多媒 ...

  3. 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法

    (本文是专门针对未接触过C/S开发的初学者而写的,C/S开发高手请自动忽略啊~~) 还在写“Hello world!”式的单机程序吗?还在各种拖控件吗?是否自己都觉得有点low呢?来个质的飞跃吧!看看 ...

  4. 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程

    一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...

  5. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序使用异步及存储过程

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第九篇:为ASP.NET MVC应用程序 ...

  6. 套用GGTalk做项目的经验总结——GGTalk源码详解系列(一)

    坦白讲,我们公司其实没啥技术实力,之所以还能不断接到各种项目,全凭我们老板神通广大!要知道他每次的饭局上可都是些什么人物! 但是项目接下一大把,就凭咱哥儿几个的水平,想要独立自主.保质保量保期地一个个 ...

  7. 一步一步使用ABP框架搭建正式项目系列教程

    研究ABP框架好多天了,第一次看到这个框架的名称到现在已经很久了,但由于当时内功有限,看不太懂,所以就只是大概记住了ABP这个名字.最近几天,看到了园友@阳光铭睿的系列ABP教程,又点燃了我内心要研究 ...

  8. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  9. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

随机推荐

  1. three.js 根据png生成heightmap

    Three.js: render real world terrain from heightmap using open data By jos.dirksen on Tue, 07/17/2012 ...

  2. tomcat(二)--tomcat结构

    Tomcat结构及组件介绍 上面的层次结构在server.xml中有体现 <Server> <Service> <Connector> <Engine> ...

  3. 安装 CentOS 后的系统配置及软件安装备忘

    安装 CentOS 后的系统配置及软件安装备忘 // */ // ]]>   安装 CentOS 后的系统配置及软件安装备忘 Table of Contents 1 Linux 自举过程 1.1 ...

  4. aa12

    option = { backgroundColor: '#1b1b1b', color: ['gold','aqua','lime'], title : { text: '模拟迁徙', subtex ...

  5. int main(int argc,char* argv[])详解

    argc是命令行总的参数个数 argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数, 比如:       int   main(int   argc,   ...

  6. 《CODE》读后笔记——第21~25章

    21.总线连接 总线是提供给计算机中每块电路板的数字信号的集合,这些信号可以分为4类:地址信号,数据输入信号,数据输出信号,控制信号.另外,总线给计算机中的各个电路板提供电源. S-100总线:早期流 ...

  7. WampServer3.0.4 允许外网访问配置教程

    原文地址:http://jingyan.baidu.com/album/acf728fd556c93f8e410a344.html?picindex=1

  8. c++ chap1 to chap 3

    #ifndef MAIN_H_INCLUDED#define MAIN_H_INCLUDED struct Course{ int id; std::string name;}; const int ...

  9. selenium隔离环境安装、以及示例

    1.virtual虚拟环境---分割项目---类似于创建文件夹---复制主环境 2.Python -n venv +目录 注意须在win环境下 3.激活虚拟环境 目录\Scripts\activate ...

  10. winfrom调用FastReport模板

    '存放模板的路径 If Dir(Application.StartupPath & "\ReportsFile\HB\01\IN.frx", FileAttribute.N ...