Socket开发框架之消息的回调处理
在一般的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开发框架之消息的回调处理相关推荐
- python 网络编程之Socket通信案例消息发送与接收
背景 网络编程是python编程中的一项基本技术.本文将实现一个简单的Socket通信案例消息发送与接收 正文 在python中的socket编程的大致流程图如上所示 我们来首先编写客户端的代码: # ...
- Android socket 编程 实现消息推送(二)
上篇文章Android socket 编程 实现消息推送(一)讲到socket编程的消息推送原理,现在我们来看看基于Android客户机socket编程实现消息推送的过程. 根据消息推送的原理图,我们 ...
- Android socket 编程 实现消息推送
最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图: 原理 ...
- Android socket 编程 实现消息推送(一)
最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图 ...
- socket接收的消息怎么更新到页面_利用socketio实现简易即时消息服务
背景简介 以前开发HTTP服务器更多使用的是python语言中的Flask框架来完成,但是在最近的业务中涉及到在web页面中实时获取消息更新,这个时候我能想到的解决方案 1.写一个循环ajax请求,不 ...
- 微信小程序添加全局 socket 并接收消息通知
最近小程序中有使用到socket,来建立长连接,实现消息通知.总结一下实现思路. 首先,在app.js中初始化socket,并处理消息,添加心跳检测. App({globalData: {suppli ...
- Socket发完消息后,立即关闭连接,客户端丢失数据的问题
使用.net编写服务器程序的时候,发现一个现象:如果服务器发完消息,立即关闭连接,客户端将无法收到服务器最后发的那条消息.个人猜想,会不会socket也有象文件流类似的缓存机制.果断利用visual ...
- socket接收的消息怎么更新到页面_spring boot 集成 websocket 实现消息主动
前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单向的,在很多场景就不适合,比如实时的推送,消息通知或者股票等信息 ...
- Socket开发框架之框架设计及分析
虽然在APP应用.Web应用.Winform应用等大趋势下,越来越多的企业趋向于这些应用系统开发,但是Socket的应用在某些场合是很必要 的,如一些停车场终端设备的接入,农业或者水利.压力监测方面的 ...
最新文章
- Eclipse中怎样使用ERMaster进行单表设计并导出为DDL
- jquery实现登录失败提示_浅谈jQuery的verify验证码
- 信息学奥赛一本通(C++)在线评测系统——基础(三)数据结构 —— 1339:【例3-4】求后序遍历
- 编码文件AndroidStudio初体验:解决Execution failed for task ':TestAndroid:compileDebug'.
- kafka 分区分配及再平衡总结
- 大数据产品开发流程规范_华为内部资料流出!揭秘华为数据湖:3大特点、6个标准、入湖流程...
- 塞尔达传说gba_1986版塞尔达 回顾34年经典系列历代作品 满分最多系列游戏
- 河流逻辑结构图生成方法
- UNIX环境高级编程之第7章:进程环境
- 手机上怎么制作电子版证件照
- 微信小程序如何被微信搜索收录?开启页面收录功能,被评定为达标
- word2010转html默认页面视图,word2010中,切换到页面视图方式的组合键
- MSP430FR5994LannchPad开发笔记之三:MSP430的IO复用以及如何去获取IO复用功能
- C 判断 —— switch语句(输入的年份判断是否为闰年,根据输入的月份判断这月有多少天)
- 有关MSSQL2000在Win7上的安装
- 终于在linux上用wine装上qq了
- TELEPORTSTONE.LUA --传送宝石
- antDesign 自定义分页样式
- 2020年中国数字减影血管造影系统(DSA)市场现状分析,DSA设备需求不断提升「图」
- 中国叉车行业发展现状及趋势分析,无人叉车将成为未来发展趋势「图」