在一般的Socket应用里面,很多时候数据的发送和接收是分开处理的,也就是我们发送一个消息,不知道这个请求消息什么时候得到应答消息,而且收到对应的应答消息的时候,如果操作界面的内容,也是需要特别处理的,因为它们和界面线程是不在一起的。如果我们在发送消息的时候,能够给一段回调的代码给收到应答消息的时候处理,那么就会方便很多。本文主要介绍如何在Socket应用里面,通过回调函数的处理,实现收到应答消息的时候能够调用对应的函数。

1、回调函数的设计

在上一篇的随笔里面,介绍了基于Json的Socket消息的实体类设计,其中包括了消息回调ID和是否在调用后移除回调两个属性,这个是用来为回调处理服务的,如下所示。

也就是在通用消息对象BaseMessage类里面添加下面两个属性。

但我们需要发送消息的时候,我们把回调的ID添加到本地集合里面,得到应答的时候,在从集合里面提出来,执行就可以了。

        /// <summary>/// 发送通用格式的数据对象/// </summary>/// <param name="data">通用的消息对象</param>/// <returns></returns>public bool SendData(BaseMessage data, Delegate callBack = null){AddCallback(callBack, data);//添加回调集合var toSendData = PackMessage(data);var result = SendData(toSendData);return result;}

        /// <summary>/// 记录回调的函数信息/// </summary>/// <param name="callBack"></param>/// <param name="msg"></param>private void AddCallback(Delegate callBack, BaseMessage msg){if (callBack != null){Guid callbackID = Guid.NewGuid();ResponseCallbackObject responseCallback = new ResponseCallbackObject(){ID = callbackID,CallBack = callBack};msg.CallbackID = callbackID;callBackList.Add(responseCallback);}}

在服务端,需要根据请求的消息构建应答内容,因此我们在应答请求的时候,需要把请求的回调ID给复制到应答的消息体里面,如下所示。

        /// <summary>/// 封装数据进行发送(复制请求部分数据)/// </summary>/// <returns></returns>public BaseMessage PackData(BaseMessage request){BaseMessage info = new BaseMessage(){MsgType = this.MsgType,Content = this.SerializeObject(),CallbackID = request.CallbackID};if(!string.IsNullOrEmpty(request.ToUserId)){info.ToUserId = request.FromUserId;info.FromUserId = request.ToUserId;}return info;}

2、本地回调函数的处理及界面处理

调用方在收到服务器的应答消息的时候,会根据回调的ID ,从本地集合里面调出来并执行处理,实现了我们回调的操作。

                var md5 = MD5Util.GetMD5_32(message.Content);if (md5 == message.MD5){InvokeMessageCallback(message, message.DeleteCallbackAfterInvoke);//触发回调
OnMessageReceived(message);//给子类重载}

        /// <summary>/// 执行回调函数/// </summary>/// <param name="msg">消息基础对象</param>/// <param name="deleteCallback">是否移除回调</param>private void InvokeMessageCallback(BaseMessage msg, bool deleteCallback){var callBackObject = callBackList.SingleOrDefault(x => x.ID == msg.CallbackID);if (callBackObject != null){if (deleteCallback){callBackList.Remove(callBackObject);}callBackObject.CallBack.DynamicInvoke(msg);}}

这样,我们在调用的时候,传入一个回调的Action,让收到消息后进行动态执行就可以了。例如在登陆的时候,我们如果需要在登陆成功后显示主窗体,那么可以执行下面的处理代码。

            var request = new AuthRequest(userNo, password);var message = request.PackData();Singleton<CommonManager>.Instance.Send(message, (msg) =>{var instance = Singleton<CommonManager>.Instance;try{var response = JsonTools.DeserializeObject<AuthResponse>(msg.Content);if (response.ValidateResult == 0){instance.ShowLoadFormText("登录成功,加载基础数据。。。。");//放置初始化代码Portal.gc.User = new User(userNo);instance.SetClientId(userNo);instance.ShowMainForm();instance.CloseLoadForm();}else{instance.CloseLoadForm();instance.ShowMessage("登录失败:" + response.Message);instance.ShowLogin();}}catch (Exception ex){instance.ShowMessage("初始化异常:" + ex.Message);instance.Exit();}});

或者我们来看看另外一个例子,这个例子是在用户登陆的时候,请求一次在线用户列表,如果用户在线,那么在界面上展示列表,具体操作代码如下所示,也是利用了回调函数的处理方式。

        /// <summary>/// 发送获取在线用户列表的请求,并在收到应答数据后进行本地界面更新/// </summary>private void RefreshUser(){CommonRequest request = new CommonRequest(DataTypeKey.UserListRequest);var data = request.PackData();Singleton<CommonManager>.Instance.Send(data, (msg) =>{UserListResponse response = JsonTools.DeserializeObject<UserListResponse>(msg.Content);if (response != null){this.InvokeUI(() =>{this.listView1.Items.Clear();foreach (CListItem item in response.UserList){if (item.Value != Portal.gc.User.UserNo){this.listView1.Items.Add(item.Text, 0);}}});}});}

例如,客户端登陆几个用户后,用户可以获得在线用户列表,界面展示如下所示。

以上就是我们在Socket应用里面处理回调函数的实现过程,这样处理可以很好利用回调代码来封装处理的细节,对于理解相关的应答操作也是很直观的。

本文转自博客园伍华聪的博客,原文链接:Socket开发框架之消息的回调处理,如需转载请自行联系原博主。

Socket开发框架之消息的回调处理相关推荐

  1. python 网络编程之Socket通信案例消息发送与接收

    背景 网络编程是python编程中的一项基本技术.本文将实现一个简单的Socket通信案例消息发送与接收 正文 在python中的socket编程的大致流程图如上所示 我们来首先编写客户端的代码: # ...

  2. Android socket 编程 实现消息推送(二)

    上篇文章Android socket 编程 实现消息推送(一)讲到socket编程的消息推送原理,现在我们来看看基于Android客户机socket编程实现消息推送的过程. 根据消息推送的原理图,我们 ...

  3. Android socket 编程 实现消息推送

    最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图:    原理 ...

  4. Android socket 编程 实现消息推送(一)

    最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图        ...

  5. socket接收的消息怎么更新到页面_利用socketio实现简易即时消息服务

    背景简介 以前开发HTTP服务器更多使用的是python语言中的Flask框架来完成,但是在最近的业务中涉及到在web页面中实时获取消息更新,这个时候我能想到的解决方案 1.写一个循环ajax请求,不 ...

  6. 微信小程序添加全局 socket 并接收消息通知

    最近小程序中有使用到socket,来建立长连接,实现消息通知.总结一下实现思路. 首先,在app.js中初始化socket,并处理消息,添加心跳检测. App({globalData: {suppli ...

  7. Socket发完消息后,立即关闭连接,客户端丢失数据的问题

    使用.net编写服务器程序的时候,发现一个现象:如果服务器发完消息,立即关闭连接,客户端将无法收到服务器最后发的那条消息.个人猜想,会不会socket也有象文件流类似的缓存机制.果断利用visual ...

  8. socket接收的消息怎么更新到页面_spring boot 集成 websocket 实现消息主动

    前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单向的,在很多场景就不适合,比如实时的推送,消息通知或者股票等信息 ...

  9. Socket开发框架之框架设计及分析

    虽然在APP应用.Web应用.Winform应用等大趋势下,越来越多的企业趋向于这些应用系统开发,但是Socket的应用在某些场合是很必要 的,如一些停车场终端设备的接入,农业或者水利.压力监测方面的 ...

最新文章

  1. Eclipse中怎样使用ERMaster进行单表设计并导出为DDL
  2. jquery实现登录失败提示_浅谈jQuery的verify验证码
  3. 信息学奥赛一本通(C++)在线评测系统——基础(三)数据结构 —— 1339:【例3-4】求后序遍历
  4. 编码文件AndroidStudio初体验:解决Execution failed for task ':TestAndroid:compileDebug'.
  5. kafka 分区分配及再平衡总结
  6. 大数据产品开发流程规范_华为内部资料流出!揭秘华为数据湖:3大特点、6个标准、入湖流程...
  7. 塞尔达传说gba_1986版塞尔达 回顾34年经典系列历代作品 满分最多系列游戏
  8. 河流逻辑结构图生成方法
  9. UNIX环境高级编程之第7章:进程环境
  10. 手机上怎么制作电子版证件照
  11. 微信小程序如何被微信搜索收录?开启页面收录功能,被评定为达标
  12. word2010转html默认页面视图,word2010中,切换到页面视图方式的组合键
  13. MSP430FR5994LannchPad开发笔记之三:MSP430的IO复用以及如何去获取IO复用功能
  14. C 判断 —— switch语句(输入的年份判断是否为闰年,根据输入的月份判断这月有多少天)
  15. 有关MSSQL2000在Win7上的安装
  16. 终于在linux上用wine装上qq了
  17. TELEPORTSTONE.LUA --传送宝石
  18. antDesign 自定义分页样式
  19. 2020年中国数字减影血管造影系统(DSA)市场现状分析,DSA设备需求不断提升「图」
  20. 中国叉车行业发展现状及趋势分析,无人叉车将成为未来发展趋势「图」

热门文章

  1. 真机调试 —— An unknown error occurred.
  2. jquery 设置 select 默认值方法
  3. jQuery:将文本转化成JSON对象应注意的问题
  4. [Data Pump]impdp导入笔记
  5. Linux之touch命令
  6. 在线文本转二进制工具
  7. jmap查询JVM堆内存
  8. 1117 Eddington Number
  9. SDWebImage 笔记
  10. Java基础——增强for循环(foreach)