上篇博客 循序渐进做项目系列(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. jfreechart 整合sturts2牛刀小试

    一.增加的jar包 struts2-jfreechart-plugin-2.1.6.jar      在struts2的相应jar包中找 jcommon-1.0.23.jar              ...

  2. POJ 3281 Dining 最大流

    饮料->牛->食物. 牛拆成两点. //#pragma comment(linker, "/STACK:1024000000,1024000000") #include ...

  3. 纯CSS实现Tooltip

    DEMO: span{ position:relative; display:inline-block; height:3em; width:3em; margin:0 0.4em; line-hei ...

  4. python 入门学习之环境搭载

    1.常用python 2.7 需要在我的电脑环境变量进行环境搭载 2.用notepad++进行编辑器适配,选择python语言 在输入运行程序名里面输入cmd /k x: & cd " ...

  5. photo shop替换颜色(自己指定的颜色)

    点开"选择"-"色彩范围",在选择下拉菜单里选"取样颜色",吸取图片上的要改的颜色,"确定",左下角拾色器前景色用你希望 ...

  6. ue4 NewObject/StaticConstructObject_Internal/StaticAllocateObject/FObjectInitializer:对象创建和初始化

    UObject是一套很复杂的体系,之前读ue3代码时曾分析过其类型系统实现,主要是与UClass间的关系 现在转到ue4,发现那一块其实差不多,于是再重点备忘一下UObject本身的创建和初始化过程 ...

  7. sprintf()函数,把数字转换成字符串

    char str_2[10];     int a=1234321;     sprintf(str_2,"%d",a);

  8. 对象的比较与排序:IComparable和IComparer接口

    IComparable和ICompare 接口是.net framework 中比较对象的标准方式,这两个接口提供一个返回值类似(大于0 等于0 小于0)的比较方法,二者区别如下: . ICompar ...

  9. GDI+ 发生一般性错误解决办法

    错误的代码g对象继续占用 未释放资源 如果路径不一样 没问题 相同路径 获取图片进行 缩略会造成GDI错误 /// <summary> /// 生成缩略图 /// </summary ...

  10. STL的迭代器和类型萃取

    今天就可以把STL库中迭代器的实现,和类型萃取好好整理一下了 迭代器的设计思维是STL的关键所在,在STL的实际运用和泛型思维,迭代器都扮演着十分重要的角色,STL力求把数据容器和算法的概念分开来,于 ...