上篇博客 循序渐进做项目系列(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. CR LF的由来

    学习Esperanto时用到一款叫做Kajero的软件,支持世界语特殊字符编辑. 在Option菜单中有个选项,End of line 列出了四种换行方式 这四种都是由基本CR和LF组成.那么CR和L ...

  2. Error:SSL peer shut down incorrectly

    从别的地方拷贝过来的项目有时会报这个错误,解决方法 File -> Project Structure -> project 对比本地项目和拷贝项目并修改至与本地项目一致

  3. RTP在。net中的使用(资料)

    开源组件:lumisoft 网址:http://www.lumisoft.ee/lswww/download/downloads/Examples/ 非开源的免费组建:rtp.net (微软推荐)

  4. X-UA-Compatible失效问题

    有时候发现页面中写了<meta http-equiv="X-UA-Compatible" content="IE=8" />,但是文档模式依旧没改变 ...

  5. 运费模版源码(.net)

    之前写了一篇关于nop商城系统中运费模版模块相关的随笔,说要把源码贴出来,一直没有贴,现在我把源码贴出来,有任何问题欢迎留言讨论. 源码是在nop上写的,所以文件夹结构和nop的文件夹对应,源码包含的 ...

  6. Linux中的工作管理(Job Control )

    以前使用Linux老是会不小心按下Ctrl + z,然后就出现看不懂的情况,以为程序突然就没了,今天专门研究了下Linux下的几个快捷键和工作管理. 其中找到一篇很不错的文章,大部分是里面转载的. 原 ...

  7. Reveal分析IOS界面,plist文件读取

    Reveal分析IOS界面,需要得到app的 softwareVersionBundleId上传到iphone中 , 而IOS8的iTunesMetadata.plist (设备路径/var/mobi ...

  8. cxf+spring+数字签名开发webservice(二)

    场景         上一章中的webservice接口,因为现场正式环境的项目与外部单位网络不通,是通过前置机与外部进行数据交换,所以我们将webservice部署在前置机,在使用HttpURLCo ...

  9. 阿里云 centos 安装apache和php

    mysql使用阿里云的rds httpd服务 1. 安装apr和apr-util 2. 安装 httpd apache.org,apr.apache.org 安装命令: ./configure --p ...

  10. OD使用教程12

    载入程序输入关键字: 双击进入程序 仔细看发现并没有跳转直接跳到这个mov,往上看发现retn上面有一个push,在这种编写手法当中这种组合相当于一个jmp, 跳到离它最近的一个值(在这就是004A5 ...