TCP在网络通讯的时候,通常在解决TCP粘包、拆包问题的时候,一般会用以下几种方式:

  1、 消息定长 例如每个报文的大小固定为200个字节,如果不够,空位补空格;

  2、 在消息尾部添加特殊字符进行分割,如添加回车;

  3、 将消息分为消息体和消息头,在消息头里面包含表示消息长度的字段,然后进行业务逻辑的处理。

  在Netty中我们主要利用对象的序列化进行对象的传输,虽然Java本身的序列化也能完成,但是Java序列化有很多问题,如后字节码流太大,以及序列化程度太低等。Jboss的序列化有程度较高、序列化后码流较小。这里利用Jboss的Marshalling测试一个简单的对象序列化。

  新建Maven工程,引入Netty5和Jboss的Marshalling。

  注:这里的Marshalling的版本,如果版本太低,可能会出现消息发送失败的问题。我在测试的时候起先用的是1.3.9,结果就是消息发送失败,打印异常信息发现是空指针的问题。

        <dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-serial</artifactId>
<version>2.0.0.Beta2</version>
</dependency>

  1、服务端

package com.netty.parry.ende4;

import com.netty.parry.ende3.MarshallingCodeCFactory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { public void start(int port) throws Exception {
// 配置NIO线程组
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
// 服务器辅助启动类配置
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.option(ChannelOption.SO_RCVBUF, 32 * 1024)
.option(ChannelOption.SO_SNDBUF, 32 * 1024)
.option(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChildChannelHandler());
// 绑定端口 同步等待绑定成功
ChannelFuture f = b.bind(port).sync();
// 等到服务端监听端口关闭
f.channel().closeFuture().sync();
} finally {
// 优雅释放线程资源
workGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
} /**
* 网络事件处理器
*/
private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 添加Jboss的序列化,编解码工具
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
// 处理网络IO
ch.pipeline().addLast(new ServerHandler());
}
} public static void main(String[] args) throws Exception {
new Server().start(8765);
}
}

  2、服务端IO处理类

package com.netty.parry.ende4;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class ServerHandler extends ChannelHandlerAdapter { // 用于获取客户端发送的信息
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 用于获取客户端发来的数据信息
Message body = (Message) msg;
System.out.println("Server接受的客户端的信息 :" + body.toString()); // 写数据给客户端
Message response = new Message("欢迎您,与服务端连接成功");
// 当服务端完成写操作后,关闭与客户端的连接
ctx.writeAndFlush(response);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

  3、客户端

package com.netty.parry.ende4;

import com.netty.parry.ende3.MarshallingCodeCFactory;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; public class Client {
/**
* 连接服务器
*
* @param port
* @param host
* @throws Exception
*/
public void connect(int port, String host) throws Exception {
// 配置客户端NIO线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
// 客户端辅助启动类 对客户端配置
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new MyChannelHandler());
// 异步链接服务器 同步等待链接成功
ChannelFuture f = b.connect(host, port).sync();
// 等待链接关闭
f.channel().closeFuture().sync(); } finally {
group.shutdownGracefully();
System.out.println("客户端优雅的释放了线程资源...");
} } /**
* 网络事件处理器
*/
private class MyChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("MyChannelHandler");
// 添加Jboss的序列化,编解码工具
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
// 处理网络IO
ch.pipeline().addLast(new ClientHandler());
}
} public static void main(String[] args) throws Exception {
new Client().connect(8765, "127.0.0.1");
}
}

  4、客户端IO处理类

package com.netty.parry.ende4;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter { // 客户端与服务端,连接成功的售后
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 发送消息
Message request1 = new Message("666");
ctx.writeAndFlush(request1).addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
System.out.println("成功发送到服务端消息");
} else {
System.out.println("失败服务端消息失败:"+future.cause().getMessage());
future.cause().printStackTrace();
}
}
});
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
Message response = (Message) msg;
System.out.println(response);
} finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

  5、消息体

package com.netty.parry.ende4;

import java.io.Serializable;

public class Message implements Serializable{

    /**
*
*/
private static final long serialVersionUID = -5296315429304117678L; private String body; public String getBody() {
return body;
} public void setBody(String body) {
this.body = body;
} public Message(String body) {
super();
this.body = body;
} public Message() {
super();
} @Override
public String toString() {
return "Message [body=" + body + "]";
}
}

  

Netty5+Jboss(Marshalling)完成对象序列化传输的更多相关文章

  1. netty: marshalling传递对象,传输附件GzipUtils

    netty: marshalling传递对象,传输附件GzipUtils 前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化.可以使用java进行对象序列化,netty去传输,但ja ...

  2. netty 对象序列化传输示例

    package object.server.impl; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Chann ...

  3. netty: 编解码之jboss marshalling, 用marshalling进行对象传输

    jboss marshalling是jboss内部的一个序列化框架,速度也十分快,这里netty也提供了支持,使用十分方便. TCP在网络通讯的时候,通常在解决TCP粘包.拆包问题的时候,一般会用以下 ...

  4. netty系列之:使用Jboss Marshalling来序列化java对象

    目录 简介 添加JBoss Marshalling依赖 JBoss Marshalling的使用 总结 简介 在JAVA程序中经常会用到序列化的场景,除了JDK自身提供的Serializable之外, ...

  5. netty 的 JBoss Marshalling 编码解码

    一. JBoss Marshalling 简介. JBoss Marshalling 是一个Java 对象序列化包,对 JDK 默认的序列化框架进行了优化,但又保持跟 Java.io.Serializ ...

  6. netty权威指南学习笔记八——编解码技术之JBoss Marshalling

    JBoss Marshalling 是一个java序列化包,对JDK默认的序列化框架进行了优化,但又保持跟java.io.Serializable接口的兼容,同时增加了一些可调参数和附加特性,这些参数 ...

  7. Java对象序列化剖析

    对象序列化的目的 1)希望将Java对象持久化在文件中 2)将Java对象用于网络传输 实现方式 如果希望一个类的对象可以被序列化/反序列化,那该类必须实现java.io.Serializable接口 ...

  8. C#对象序列化与反序列化zz

      C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...

  9. C#对象序列化与反序列化

    C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍.......................... ...

随机推荐

  1. flask 跨域问题

    在Flask开发RESTful后端时,前端请求会遇到跨域的问题.下面是解决方法.Python版本:3.5.1 下载flask_cors包 pip install flask-cors使用flask_c ...

  2. JQ04

    1.JQ插件 使用插件扩展jq的功能 1)插入插件的步骤: 引入JQ文件,引入插件,若有用到css,需要引入css.使用插件. 2)jquery.color.js <!DOCTYPE html& ...

  3. flask之分页插件的使用、添加后保留原url搜索条件、单例模式

    本篇导航: flask实现分页 添加后保留原url搜索条件 单例模式 一.flask实现分页 1.django项目中写过的分页组件 from urllib.parse import urlencode ...

  4. WordPress主题开发:footer.php

    最简 <?php wp_footer();?> </body> </html>

  5. Go语言无锁队列组件的实现 (chan/interface/select)

    1. 背景 go代码中要实现异步很简单,go funcName(). 但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用"协程池 + 无锁队列"实现. 2. golang ...

  6. 【Kibana】自定义contextPath

    #https://www.elastic.co/guide/en/kibana/5.0/_configuring_kibana_on_docker.html#https://discuss.elast ...

  7. 无法解析依赖项。“Microsoft.Net.Http 2.2.29”与 'Microsoft.Net.Http.zh-Hans

    无法解析依赖项.“Microsoft.Net.Http 2.2.29”与 'Microsoft.Net.Http.zh-Hans 2.0.20710 约束: Microsoft.Net.Http (= ...

  8. 腾讯云服务器web环境配置过程

    我买的服务器是: 可用区:香港二区 实例类型:标准型S2 操作系统:CentOS 6.5 64位 自己的电脑是 win10 ------------以上是背景------------------ 1 ...

  9. mina websocket 粘包、断包、(丢包)解决心得

    被这3个(其实是2个)问题坑惨了,目前没发现存在丢包问题,之前认为的丢包问题事实是不存在的. 粘包和断包的情况是存在的,这两个问题不怕,只要发送接收到的数据包顺序没有被打乱颠倒,一切都好办. 容易掉的 ...

  10. matplotlib 与 seaborn 中出现中文乱码的解决方法

      Linux.Mac osx 系统中,出现 matplotlib 或 seaborn 绘图中有中文乱码的情形,可以考虑使用以下方式处理: 到 anaconda 的 matplotlib 中查看是否有 ...