mina client和server端传输和接收java对象,是java序列化和反序列化的过程。

mina-core包中有对这一块encoder-decoder的编解码类。

ObjectSerializationCodecFactory是工厂类,在client和server端配置coder filter时使用到。ObjectSerializationEncoder是序列化编码类,ObjectSerializationDecoder是序列化解码类

先看运行代码

server端

IoAcceptor accepter = new NioSocketAcceptor();

ProtocolCodecFilter coderFilter =

//ObjectSerializationCodecF

new ProtocolCodecFilter(new ObjectSerializationCodecFactory());

accepter.getFilterChain().addLast("a", new LoggingFilter());

accepter.getFilterChain().addLast("b",coderFilter);

accepter.setHandler(new ObjectServerHandler());

accepter.getSessionConfig().setReadBufferSize(2048);

accepter.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);

accepter.bind(new InetSocketAddress(8484));

传输的简单java对象:

public class SimpleObj implements Serializable {

/****/

private static final long serialVersionUID = 8217287396365894807L;

private String name;

private String count;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getCount() {

return count;

}

public void setCount(String count) {

this.count = count;

}

}

server端handler

public class ObjectServerHandler extends IoHandlerAdapter{

@Override

public void exceptionCaught( IoSession session, Throwable cause ) throws Exception

{

cause.printStackTrace();

session.close(true);

}

@Override

public void messageReceived( IoSession session, Object message ) throws Exception

{

SimpleObj obj = (SimpleObj) message;

System.out.println(obj.getName()+":"+obj.getCount());

session.write(obj);

}

}

client端handler

public class ObjectClientHandler extends IoHandlerAdapter {

private SimpleObj obj;

public ObjectClientHandler(SimpleObj obj){

this.obj = obj;

}

@Override

public void sessionOpened(IoSession session) throws Exception {

session.write(obj);

}

@Override

public void messageReceived(IoSession session, Object message)

throws Exception {

System.out.println(message.toString());

}

@Override

public void exceptionCaught(IoSession session, Throwable cause)

throws Exception {

session.close(true);

}

}

client端

NioSocketConnector connector = new NioSocketConnector();

connector.setConnectTimeoutMillis(20000);

connector.getFilterChain().addLast("codes", new ProtocolCodecFilter(

new ObjectSerializationCodecFactory()));

SimpleObj obj = new SimpleObj();

obj.setName("bird");

obj.setCount("7");

connector.setHandler(new ObjectClientHandler(obj));

IoSession session = null;

ConnectFuture future = connector.connect(new InetSocketAddress("localhost", 8484));

future.awaitUninterruptibly();

session = future.getSession();

session.getCloseFuture().awaitUninterruptibly();

connector.dispose();

先启动server端服务,运行client端,server端就可收到传输的object。打印出bird:7

ObjectSerializationEncoder的encoder方法是序列化开始

org.apache.mina.filter.codec.serialization.ObjectSerializationEncoder

public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {

//没序列化,直接抛异常

if (!(message instanceof Serializable)) {

throw new NotSerializableException();

}

IoBuffer buf = IoBuffer.allocate(64);

buf.setAutoExpand(true);

//A 将Object序列化后字节内容填充到buffer内

buf.putObject(message);

//对象序列化后字节长度,大于最大值就抛异常,一般应该没这么大

//maxObjectSize = Integer.MAX_VALUE;

int objectSize = buf.position() - 4;

if (objectSize > maxObjectSize) {

throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + maxObjectSize

+ ')');

}

buf.flip();

out.write(buf);

}

A处方法源码 org.apache.mina.core.buffer.AbstractIoBuffer

public IoBuffer putObject(Object o) {

int oldPos = position();

skip(4); // 前4个长度先跳过,预留存储对象长度

try {

ObjectOutputStream out = new ObjectOutputStream(asOutputStream()//B,下面介绍) {

//重写了ObjectOutputStream的一个方法,不知道干什么用,

@Override

protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {

try {

Class> clz = Class.forName(desc.getName());

if (!Serializable.class.isAssignableFrom(clz)) { // NON-Serializable class

write(0);

super.writeClassDescriptor(desc);

} else { // Serializable class

write(1);

writeUTF(desc.getName());

}

} catch (ClassNotFoundException ex) { // Primitive types

write(0);

super.writeClassDescriptor(desc);

}

}

};

//和普通的java序列化一样,调用writeObject方法,java序列化前面文章有说过

out.writeObject(o);

out.flush();

} catch (IOException e) {

throw new BufferDataException(e);

}

// 填写前面预留的长度位

int newPos = position();//当前position

position(oldPos);//position标到开始位0

putInt(newPos - oldPos - 4);//将object字节长度写入

position(newPos);//postion到buffer的结尾

return this;

}

B处 asOutputStream()方法,就是实例化一个OutputStream,

两个写方法都是把内容放到IoBuffer里。

后续的Stream包装类,也就是ObjectOutputStream不管是writeShort,writeUTF等等也好,

最后都是调用这两个方法,所以上面的writeObject最后都是把object的内容写到了

IoBuffer里

public OutputStream asOutputStream() {

return new OutputStream() {

@Override

public void write(byte[] b, int off, int len) {

AbstractIoBuffer.this.put(b, off, len);

}

@Override

public void write(int b) {

AbstractIoBuffer.this.put((byte) b);

}

};

}

所以encode完后,传到server端的buffer内容

buffer=4个长度位+object序列化后的字节内容(序列化稍微差别,上面重写了个方法)

C处out方法源码

org.apache.mina.filter.codec.AbstractProtocolEncoderOutput

public void write(Object encodedMessage) {

if (encodedMessage instanceof IoBuffer) {

IoBuffer buf = (IoBuffer) encodedMessage;

if (buf.hasRemaining()) {

messageQueue.offer(buf);

} else {

throw new IllegalArgumentException("buf is empty. Forgot to call flip()?");

}

} else {

messageQueue.offer(encodedMessage);

buffersOnly = false;

}

}

下面看server端解码:

org.apache.mina.filter.codec.serialization.ObjectSerializationDecoder

protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {

//不足4个长度就直接不处理了,前面encode的过程肯定>4

if (!in.prefixedDataAvailable(4, maxObjectSize)) {

return false;

}

//AA 首先从buffer里吧序列化的对象读出来,反序列化

//依次读取出来

out.write(in.getObject(classLoader));

return true;

}

AA处getObject方法源码

public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException {

if (!prefixedDataAvailable(4)) {

throw new BufferUnderflowException();

}

//读取一个int,也就是读取前面encode的标示位

int length = getInt();

if (length <= 4) {

throw new BufferDataException("Object length should be greater than 4: " + length);

}

int oldLimit = limit();

limit(position() + length);

try {

ObjectInputStream in = new ObjectInputStream(asInputStream()//BB) {

//略去两个重写ObjectInputStream方法

};

//和普通java反序列化一样调用ObjectInputStream.readObject()方法

return in.readObject();

} catch (IOException e) {

throw new BufferDataException(e);

} finally {

limit(oldLimit);

}

}

BB处源码org.apache.mina.core.buffer.AbstractIoBuffer

也是从buffer中读取序列化内容

public InputStream asInputStream() {

return new InputStream() {

@Override

public int available() {

return AbstractIoBuffer.this.remaining();

}

@Override

public synchronized void mark(int readlimit) {

AbstractIoBuffer.this.mark();

}

@Override

public boolean markSupported() {

return true;

}

@Override

public int read() {

if (AbstractIoBuffer.this.hasRemaining()) {

return AbstractIoBuffer.this.get() & 0xff;

}

return -1;

}

@Override

public int read(byte[] b, int off, int len) {

int remaining = AbstractIoBuffer.this.remaining();

if (remaining > 0) {

int readBytes = Math.min(remaining, len);

AbstractIoBuffer.this.get(b, off, readBytes);

return readBytes;

}

return -1;

}

@Override

public synchronized void reset() {

AbstractIoBuffer.this.reset();

}

@Override

public long skip(long n) {

int bytes;

if (n > Integer.MAX_VALUE) {

bytes = AbstractIoBuffer.this.remaining();

} else {

bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);

}

AbstractIoBuffer.this.skip(bytes);

return bytes;

}

};

}

java mina 大文件传输_mina 传输java对象相关推荐

  1. java 读取txt,java读取大文件

    java 读取txt,java读取大文件 package com.bbcmart.util; import java.io.File; import java.io.RandomAccessFile; ...

  2. java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

    http://langgufu.iteye.com/blog/2107023 java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果 ...

  3. 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码. file ...

  4. Java 高效大文件 读取 和 写入(一亿行)

    写文件 需求:写入1亿行,7位以内的随机的数字. 首先看成果图,代表没骗大家!!!!! 这个是最终生成的文件,有770多MB .下面用glogg打开预览: 程序打印耗时 7149ms + 923 ms ...

  5. java实现大文件分片上传

    java实现大文件分片上传 在项目中用到了大文件上传功能,最初从网上参考了一些代码来实现,但是最终的上传效果不是很好,速度比较慢. 之前的上传思路是: 前端利用webUploader分片大文件 后端接 ...

  6. java qq 传送文件_如何利用Java实现QQ文件传输功能.pdf

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspJava 如何利用Java实现QQ文件传输功能.pdf2页 本文 ...

  7. java io大文件_JavaIO流对大文件进行分割与合并

    对于大文件传输不方便时候可以试一下分割之后再操作: package com.lym; import java.io.BufferedInputStream; import java.io.Buffer ...

  8. java 拷贝大文件_java高效实现大文件拷贝功能

    在java中,FileChannel类中有一些优化方法可以提高传输的效率,其中transferTo( )和 transferFrom( )方法允许将一个通道交叉连接到另一个通道,而不需要通过一个缓冲区 ...

  9. java实现大文件分片上传功能(前后端都有,代码down下来配置完后可以直接运行)

    问题 项目解决的问题主要是java实现分片上传功能,问题描述: 楼主在公司最近项目中使用multipart文件上传视频文件到服务器上,然后用fastdfs保存到数据库中.发现当上传的视频文件太大的时候 ...

最新文章

  1. angular2+ 自定义pipe管道实例--定义全局管道及使用
  2. 后门BROOTKIT代码学习和原理分析
  3. esp8266 阿里云 arduino_ESP8266接入阿里云——基于官方SDK接入阿里云串口获取云下发数据...
  4. rust(54)-字符串
  5. watch 和 computed
  6. jquery动态改变图片
  7. 我学到的5件事,指导2,500名有抱负的开发人员
  8. [ 逻辑锻炼] 用 JavaScript 做一个小游戏 ——2048 (详解版)
  9. (四)Linux 安装 jdk
  10. VTD信号灯TrafficLight数据解析提取
  11. 全屋wifi测试软件,全屋WIFI评测
  12. excel 行列转换
  13. Spark学习笔记1(初始spark
  14. vue 高德地图 不同区域显示不同颜色_高德地图这样用成为你的图表神器
  15. redis,Redis Desktop Manger和IDEA Iedis的安装和使用
  16. 【测试】功能测试用例设计方法总结
  17. 哪一个属于计算机外存储器,下边哪一个属于计算机的外存储器()
  18. Ubuntu 20.04添加临时/永久路由
  19. python练习:重新排列句子中的单词
  20. 无线通信中的TD系统(TD-LTE)

热门文章

  1. 写出好的 commit message
  2. 如何在命令行下运行kettle的作业(job)和转换(transform)
  3. Delphi 2010 新增功能之: IOUtils 单元(1): 初识 TDirectory.GetFiles
  4. TableLayout与MigLayout
  5. solr与zookeeper搭建solrcloud分布式索引服务实例
  6. 宝岛探险1(DFS)
  7. java搜索引擎lucene_简单lucene搜索实现(搜索引擎)
  8. 代码能跑就不要动,为什么我们都会有这样的想法?
  9. 开发是在什么部门办理_房产证办理流程是什么?办理房产证需要缴纳哪些费用?...
  10. sqlserver垮库查询_sql跨库查询(sqlserver跨库查询)