Netty学习教程之Netty与Marshalling结合发送对象

前言

之前的一篇文章是Netty简单的学习,我们可以传递一个字符串,那么如果我们想要在Netty中传递一个对象该怎么办呢 ?

那么这个时候我们可以结合Marshalling来传递。

方法如下:

首先需要导入两个Marshalling的依赖包

jboss-marshalling-1.3.0.CR9.jar
jboss-marshalling-serial-1.3.0.CR9.jar

注意:我开始学习的时候只导入了第一个jar包,没有导入第二个,结果是不报错,但是客户端和服务端之间传递不了消息。所以两个包一定要都导入才行。

MarshallingCodeCFactory工具类

public class MarshallingCodeCFactory { 

 public static MarshallingDecoder buildMarshallingDecoder() {
  final MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
  final MarshallingConfiguration configuration = new MarshallingConfiguration();
  configuration.setVersion(5);
  UnmarshallerProvider provider = new DefaultUnmarshallerProvider(factory, configuration);
  MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024*1024);
  return decoder;
 } 

 public static MarshallingEncoder buildMarshallingEncoder() {
  final MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
  final MarshallingConfiguration configuration = new MarshallingConfiguration();
  configuration.setVersion(5);
  MarshallerProvider provider = new DefaultMarshallerProvider(factory, configuration);
  MarshallingEncoder encoder = new MarshallingEncoder(provider);
  return encoder;
 }
} 

server端

public class Server { 

 public static void main(String[] args) throws InterruptedException {
  //1.第一个线程组是用于接收Client端连接的
  EventLoopGroup bossGroup = new NioEventLoopGroup();
  //2.第二个线程组是用于实际的业务处理的
  EventLoopGroup workerGroup = new NioEventLoopGroup();
  ServerBootstrap b = new ServerBootstrap();
  b.group(bossGroup, workerGroup);//绑定两个线程池
  b.channel(NioServerSocketChannel.class);//指定NIO的模式,如果是客户端就是NioSocketChannel
  b.option(ChannelOption.SO_BACKLOG, 1024);//TCP的缓冲区设置
  b.option(ChannelOption.SO_SNDBUF, 32*1024);//设置发送缓冲的大小
  b.option(ChannelOption.SO_RCVBUF, 32*1024);//设置接收缓冲区大小
  b.option(ChannelOption.SO_KEEPALIVE, true);//保持连续
  b.childHandler(new ChannelInitializer<SocketChannel>() {
   protected void initChannel(SocketChannel ch) throws Exception {
    //设置Marshalling的编码和解码
    ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
    ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
    ch.pipeline().addLast(new ServertHandler());
   }
  });
  ChannelFuture future = b.bind(8765).sync();//绑定端口
  future.channel().closeFuture().sync();//等待关闭(程序阻塞在这里等待客户端请求)
  bossGroup.shutdownGracefully();//关闭线程
  workerGroup.shutdownGracefully();//关闭线程
 } 

} 

ServerHandler处理类

public class ServertHandler extends ChannelHandlerAdapter { 

 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
   throws Exception {
  cause.printStackTrace();
 } 

 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg)
   throws Exception {
  Send send = (Send) msg;
  System.out.println("client发送:"+send); 

  Receive receive = new Receive();
  receive.setId(send.getId());
  receive.setMessage(send.getMessage());
  receive.setName(send.getName());
  ctx.writeAndFlush(receive);
 } 

} 

由于我们已经在Server端和Client端定义了传递的类型又Marshalling工厂处理,所以此时我们接收的时候直接转成发送的对象类型就行了。

Client端

public class Client { 

 public static void main(String[] args) throws InterruptedException {
  EventLoopGroup worker = new NioEventLoopGroup();
  Bootstrap b = new Bootstrap();
  b.group(worker)
  .channel(NioSocketChannel.class)
  .handler(new ChannelInitializer<SocketChannel>() {
   @Override
   protected void initChannel(SocketChannel sc) throws Exception {
    //ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
    //sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
    //sc.pipeline().addLast(new StringDecoder());
    sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
    sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
    sc.pipeline().addLast(new ClientHandler());
   }
  });
  ChannelFuture f=b.connect("127.0.0.1",8765).sync();
  for(int i=1;i<=5;i++){
   Send send = new Send();
   send.setId(i);
   send.setMessage("message"+i);
   send.setName("name"+i);
   f.channel().writeAndFlush(send);
  }
  f.channel().closeFuture().sync();
  worker.shutdownGracefully();
 }
} 

ClientHandler端

public class ClientHandler extends ChannelHandlerAdapter{
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    throws Exception {
   cause.printStackTrace();
   ctx.close();
  } 

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg)
    throws Exception {
   Receive receive = (Receive) msg;
   System.out.println("server反馈:"+receive);
  }
} 

send类

public class Send implements Serializable { 

 /**
  * serialVersionUID:TODO(用一句话描述这个变量表示什么)
  *
  * @since 1.0.0
  */ 

 private static final long serialVersionUID = 1L; 

 private Integer id;
 private String name;
 private String message; 

 public Integer getId() {
  return id;
 } 

 public void setId(Integer id) {
  this.id = id;
 } 

 public String getName() {
  return name;
 } 

 public void setName(String name) {
  this.name = name;
 } 

 public String getMessage() {
  return message;
 } 

 public void setMessage(String message) {
  this.message = message;
 } 

 @Override
 public String toString() {
  return "Send [id=" + id + ", name=" + name + ", message=" + message + "]";
 } 

} 

Receive类

public class Receive implements Serializable{ 

 /**
  * serialVersionUID:TODO(用一句话描述这个变量表示什么)
  * @since 1.0.0
  */ 

 private static final long serialVersionUID = 1L;
 private Integer id;
 private String name;
 private String message;
 private byte[] sss; 

 public byte[] getSss() {
  return sss;
 }
 public void setSss(byte[] sss) {
  this.sss = sss;
 }
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getMessage() {
  return message;
 }
 public void setMessage(String message) {
  this.message = message;
 }
 @Override
 public String toString() {
  return "Receive [id=" + id + ", name=" + name + ", message=" + message + ", sss=" + Arrays.toString(sss) + "]";
 } 

} 

注意:send类和receive这两个类,我们再真实环境开发的时候服务器和客户端往往是两个web应用程序,在这里我们要注意服务端和客户端之间的两个类类名和包名在两端要完全相同。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

时间: 2017-05-18

Netty学习教程之基础使用篇

什么Netty? Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用.Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发. 我们下面编写四个类 1.用于接收数据的服务器端Socket

kotlin 官方学习教程之基础语法详解

kotlin 官方学习教程之基础语法详解 Google 在今天的举行了 I/O 大会,大会主要主要展示内有容 Android O(Android 8.0)系统.Google Assistant 语音助手.Google 智能音箱.人工智能.机器学习.虚拟现实等.作为一个 Android 开发者,我关心的当然是 Android O(Android 8.0)系统了,那么关于 Android O 系统的一个重要消息是全面支持 Kotlin 编程语言,使得 Kotlin 成为了 Android 开发的官方

seajs学习教程之基础篇

介绍 众所周知前端开发模块化已经是大势所趋,目前模块化的规范有很多,众所周知的有commonJS,Module/Wrappings和AMD等,而且ES6也着手开始制定模块化机制的实现.类似于c/c++的include,java中的import关键字,在js中也定义了require关键字,用以引进依赖模块. 由于规范的多样性,模块化的实现也是各有各的不同. nodejs遵从的就是commonJS规范,它有着一些形式上的约定: 1.require为函数,该函数接受一个字符串作为模块标示符 2.req

RxSwift学习教程之基础篇

前言 我们在 iOS 开发过程中,几乎无时无刻都要面对异步事件的处理.例如,按键点击.数据保存..音频后台播放.交互动画展示.这些事件并不具备特定时序性,甚至它们可能同时发生. 虽然 Apple 提供了通知.代理.GCD.闭包等异步机制,但是这些机制缺乏一个统一的抽象表述.另外,这些机制在处理共享的可变数据或状态时不够清晰简练.当然,这并不是说编写优雅的异步代码不现实.毕竟与其他平台相比 iOS 的异步机制还是很强大的. 幸运的是,我们能够通过 RxSwift 优雅的处理异步代码. 至于 RxS

Vue + Webpack + Vue-loader学习教程之功能介绍篇

Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue 组件转化成JavaScript模块. vue-loader 提供了一些非常酷炫的特性: ES2015默认可用: 在每个 Vue 组件内支持其他的 Webpack 加载器,如用于<style>的 SASS 和用于<template> 的 Jade. 把 <style> 和 <template> 内引用的静态资源作为模块依赖项对待,并用Webpack 加载器处理. 对每个

Vue + Webpack + Vue-loader学习教程之相关配置篇

前言 之前已经介绍过了Vue + Webpack + Vue-loader的相关功能介绍,大家可以点击这篇文章了解详情.下面就来看看相关配置篇,感兴趣的可以参考学习. 使用预处理器 在 Webpack 中,所有的预处理器需要和一个相应的加载器一同使用.vue-loader 允许你用其它的 Webpack 加载器去处理 Vue 组件一部分代码.它会根据 lang 属性自动用适当的加载器去处理. CSS 例如,我们编译用 SASS 编译 <style> 标签: npm install sass-l

socket.io学习教程之基础介绍(一)

前言 Web端与服务器间的实时数据传输的是一个很重要的需求,但最早只能通过AJAX轮询询实现.在WebSocket标准没有推出之前,AJAX轮询是唯一可行的方式(通过Flash浏览器也可以,但这里不做讨论).AJAX轮询原理是设置定时器,定时通过AJAX同步服务器数据.这种方式存在延时且对服务端造成很大负载.直到2011年,IETF才标准化WebSocket--一种基于TCP套接字进行收发数据的协议.现如今主流浏览器均已支持WebSocket. socket.io将数据传输部分独立出来形成了en

Spring boot学习教程之快速入门篇

前言 首先来说一下为什么使用 Spring Boot,之前我用的后端 WEB 开发框架一直都是 PlayFramework的 1.2.7 版本(目前已经停止更新), 不得不说这个框架非常好用,但是由于 Play2.x 版本和 Play1.x 版本差别巨大,并且不兼容,所以现在面临着选择新的框架的问题,问了下身边的朋友,发现他们都在用 Spring ,然而我发现 Spring 的话,经常要配置各种东西,习惯了 Play 的简单明了的配置方式,确实有些不习惯 Spring ,这个时候发现了 Spri

Javascript基础学习笔记(菜鸟必看篇)

什么是变量? 变量是用于存储信息的容器 变量的声明 语法: var 变量名 变量名 = 值; 变量要先声明再赋值 变量可以重复赋值 变量的命名规则 变量必须以字母开头: 变量也能以$和_符号开头(不过我们不推荐这么做): 变量名称对大小写敏感(a和A是不同的变量). 语句 语句以一个分号结尾:如果省略分号,则由解析器确定语句的结尾. 有个好的编码习惯,都要以 ; 结尾 数据类型 在JavaScript中,一段信息就是一个值(value).值有不同的类型,大家最熟悉的类型是数字.字符串(strin

JavaScript基础教程——入门必看篇

JavaScript他是一种描述性语言,其实他并不难学,只要用心学,一定会学好,我相信大家在看这篇文章的时候,一定也学过HTML吧,使用JavaScript就是为了能和网页有更好的交互,下面切入主题. 一. JavaScript 1.什么是JavaScript JavaScript是一种描述性语言,也是一种基于对象(Object)和事件驱动(Event Driven)的,并具有安全性的脚本语言. 2.JavaScript的特点 JavaScript主要用来向HTML页面添加交互行为. JavaS