Cindy Message/MessageRecognizer interface

在用户对我的反馈中,其中最常见的就是对Message和MessageRecongizer接口的误用。
 
大家对Java里面的Serializable接口应该都不陌生吧,通过实现序列化接口,一个Java对象可以与字节流做双向转换。在网络传输中是没有对象的概念的,最基本的传输单位是字节,所以如果要通过网络来传输一个对象,就得按照如下三步来进行:

  1. 将对象转换为字节流
  2. 传输字节流
  3. 接收方接收字节流,并转换为对象

Cindy中Message接口就是这个转换的桥梁。Message接口的toByteBuffer方法就实现了该如何把这个对象转换为字节 流,readFromBuffer方法就实现了如何把字节流转换为该对象,至于传输,则由相应的Session来完成。这里要指出的Message和 Serializable接口不同的是,如果某类实现了Serializable接口,这个双向转换的过程可以由虚拟机来自动完成,而Message接口 则需要用户通过编程来明确指定转换方式。

假设有这个一个User对象需要在网络上传输:

public User {
    private String name; //假设不超过255个字节
    private byte age;
    ...get / set
}

我们可以定义若干种不同的方式将其转换为字节流,这取决于我们的业务需要。比如我们可以将其按如下的方式转换:

name UTF-8编码长度(byte) + name UTF-8编码(byte[]) + age(byte)

也可以按如下方式转换:

user对象总长度(4 byte) + age(byte) + name UTF-8编码(byte[])

如果是第一种方式,那么我们可以让这个User类实现Message接口,并且toByteBuffer方法可以这样写:

public ByteBuffer[] toByteBuffer() {
        //转换为UTF-8编码
        ByteBuffer nameBuffer = CharsetUtils.UTF-8.encode(name); 
        //第一个字节是长度,后面跟着UTF-8编码,再后面跟着age
        ByteBuffer buffer = ByteBuffer.allocate(1 + nameBuffer.remaining() + 1);
        buffer.put((byte)nameBuffer.remaining());
        buffer.put(nameBuffer);
        buffer.put(age);
        return new ByteBuffer[] {buffer};
   }

这样我们就定义好了如何将这个User对象转换为字节流了。

当从网络上读取这个User对象时,要注意的地方就要稍微多一点了。读取的时候不能假定所有的数据都已经传输完成了,很有可能这个User对象传输 到了一半的时候,就开始识别对象了,所以readFromBuffer方法返回值是boolean值,只有在该对象已经完全传输完毕的时候才返回 true,通知框架该对象已传输完毕。

比如这个User对象的readFromBuffer方法可以这样写:

public boolean readFromBuffer(ByteBuffer buffer) {
if (!buffer.hasRemaining())
    return false;
byte length = buffer.get(buffer.position());
if (buffer.remaining() < 1 + length + 1)  //消息没有接收完全,返回false
    return false;
//消息已经全部接收完,读取消息
ByteBuffer nameBuffer = (ByteBuffer) buffer.slice().position(1).limit(length+1);
name = CharsetUtils.UTF-8.decode(nameBuffer).toString();
buffer.position(buffer.position+1+length);
age = buffer.get();
return true;
}

注意红色的代码,在这里并没有用buffer.get(),而是使用了buffer.get(buffer.position())。因为这个时候 还没有确定消息是不是接收完毕,如果直接通过buffer.get()读取后,buffer的position就会发生变化,如果发现消息没有接收完毕, 返回前就需要重新将position移回到原来的位置。

比如如果要接收的User对象字节流是 3 a b c 20,第一次触发readFromBuffer方法是由于接收到了3 a b,如果这时通过buffer.get()来读取,读完后缓冲区就变成了a b,然后返回false;第二次又接收到了c 20,这时触发readFromBuffer时,缓冲区就变成了a b c 20,这时再通过buffer.get()来读取就会发生异常了。所以消息没接收完毕前,不要移动缓冲区的指针。(在这里我发现了一个似乎可以改进的地方,即如果readFromBuffer返回false,框架可以将buffer的指针重置为原值。具体影响有待考量 )

Cindy Message/MessageRecognizer interface相关推荐

  1. Ubuntu 16.04 安装 MPI(Message Passing Interface)

    参考 MPI 安装在 Ubuntu16.04 1. 下载源文件 镜像网站 https://www.mpich.org/static/downloads/3.3.2/ 官方网站 http://www.m ...

  2. gnu radio学习(三)Message Passing消息传递详解

    Message Passing Introduction(介绍) Message Passing API(消息传递端口) Message Handler Functions(消息处理函数) Conne ...

  3. 计图(Jittor) 1.1版本:新增骨干网络、JIT功能升级、支持多卡训练

    计图(Jittor) 1.1版本:新增骨干网络.JIT功能升级.支持多卡训练 深度学习框架-计图(Jittor),Jittor的新版本V1.1上线了.主要变化包括: • 增加了大量骨干网络的支持,增强 ...

  4. 计图MPI分布式多卡

    计图MPI分布式多卡 计图分布式基于MPI(Message Passing Interface),主要阐述使用计图MPI,进行多卡和分布式训练.目前计图分布式处于测试阶段. 计图MPI安装 计图依赖O ...

  5. CUDA Samples目录

    简介 Simple Reference  基础CUDA示例,适用于初学者, 反映了运用CUDA和CUDA runtime APIs的一些基本概念. Utilities Reference  演示如何查 ...

  6. wkwebView基本使用方法

    WKWebView有两个delegate,WKUIDelegate 和 WKNavigationDelegate.WKNavigationDelegate主要处理一些跳转.加载处理操作,WKUIDel ...

  7. iOS与JS交互的4种方法

    iOS与JS交互的方法: 1.拦截url(适用于UIWebView和WKWebView) 2.JavaScriptCore(只适用于UIWebView,iOS7+) 3.WKScriptMessage ...

  8. nsq php,Nsq从入门到实践

    当nsq跑起来之后, 我们可能会遇到以下问题 分布式部署 处理错误(何时requeue) 如何使用golang lib 抱着不应该只停留在入门的态度, 笔者粗浅的研究了一下这几个问题, 希望也对有同样 ...

  9. 用gdb调试mpi程序的一些心得

    Linux下MPI (Message Passage Interface) 的程序不太好调试,在windows下vs2005以上的IDE有集成的简便MPI调试工具,没有用过,有兴趣的可以试验一下.下面 ...

最新文章

  1. 半个月3篇Nature/Science,95后曹原3年8篇顶刊,网友:杀疯了杀疯了
  2. 类型转换与采样 || SMOTE算法
  3. Git多人开发场景模拟
  4. MYSQL 时间计算的 3 种函数
  5. CodeForces - 570E(dp------------- Codeforces Round #316 (Div. 2)E
  6. remove()与empty()的区别
  7. MongoDB高级——复制(副本集)
  8. 从游戏谈起——论主动性和责任心
  9. 管理感悟:图省事就是把别人当白痴
  10. win10系统设置插入鼠标禁用触控板的方法
  11. 使用Xbox360手柄控制你的turtlebot/rbx1/mrobot小车机器人
  12. mysql 访问被拒绝如何解决
  13. Pycharm下载库出错ERROR: Could not find a version that satisfies the requirement
  14. 红孩儿编辑器的模块设计15
  15. oracle服务器配置端口,服务端配置一个多端口号(如1521/1526)监听器
  16. c语言机票座位预定系统_课内资源 - 基于C语言的飞机票预订系统
  17. Android 毕业设计高仿新浪微博客户端(内附源码)
  18. python金融趋势指标计算:布林带
  19. 母亲节不能陪在妈妈身边,我用css和js给妈妈做了一个爱心飘落
  20. 商品新零售行业——客户价值分析驾驶舱(附详细操作)

热门文章

  1. 和我一起学Python,一起采集妹子图
  2. int a=1;int b=2;a与b互相交换的几种方式
  3. 最新仿猪八戒威客系统源码网整站源码下载
  4. [长安战疫-cazy] Web题解
  5. Facebook聊单,SaleSmartly有妙招!
  6. 纯软件程序员向嵌入式系统工程师转型时需注意的问题
  7. 如何上传项目到开源中国码云
  8. 珍珠bead_珍珠果酱直播
  9. Python 利用4行代码实现图片灰度化
  10. 【转】超实用网站,一次性分享出来