`
yutinglong
  • 浏览: 66423 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用mina传输大字节数组

阅读更多
使用mina传输超过2k以上的数据时(采用tcp方式,如果是UDP方式,好像一次传输的数据不能超过256字节,如果超过mina不会分批次发送,而tcp方式会分批次发送),mina会自动将这些数据分成多次发送。由于是分批次发送数据,所有客服端在接受数据时,需要等所有的数据接受完之后才能解码,否则无法解码,或者只能读取到部分文件。
以下是一个发送、接受大字节数组的主要代码
服务端向客服端发送字节数组
服务端代码:
编码器:
public class ImageDataEncoder extends ProtocolEncoderAdapter {
 @Override
 public void encode(IoSession session, Object message,
   ProtocolEncoderOutput out) throws Exception {
  CharsetEncoder charset = Charset.forName("UTF-8").newEncoder();
  ImageData image = (ImageData) message;
  IoBuffer buffer = IoBuffer.allocate(2048).setAutoExpand(true);
  buffer.putString(image.getYh(), charset);// 发送数据类型
  buffer.putInt(image.getLength());// 发送字节数组的总长度,共解码时使用
  buffer.put(image.getBimage());// 发送字节数据
  buffer.flip();
  out.write(buffer);
  buffer.free();
 }
}

ImageData.java
public class ImageData {
 private static final long serialVersionUID = 1L;
 private String yh = YHConstants.YH_IMG;// 数据类型
 public int length = 0;// 字节数组长度
 private byte[] bimage;// 待发送的字节数组
 private BufferedImage image;//将字节数组转换成图片文件
 public ImageData() {
 }
 public ImageData(byte[] bimage) {
  this.bimage = bimage;
 }
 public byte[] getBimage() {
  return bimage;
 }
 public BufferedImage getImage() {
  try {
   if (bimage.length > 0) {
    ByteArrayInputStream in = new ByteArrayInputStream(bimage);
    this.image = ImageIO.read(in);
    in.close();
   }
  } catch (RemoteException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return this.image;
 }
 public int getLength() {
  return bimage.length;
 }
 public String getYh() {
  return yh;
 }
 public void setBimage(byte[] bimage) {
  this.bimage = bimage;
 }
 public void setYh(String yh) {
  this.yh = yh;
 }
}
YHConstants.java
public class YHConstants {
 public static final int LENGTH = 7;// 命令数据类型
 public static final String YH_CMD = "YH CMD ";// 命令数据类型
 public static final String YH_IMG = "YH IMG ";// 图片数据类型
}
客服端:
解码器:分段发送的解码器一定要继承CumulativeProtocolDecoder ,这个是专门用来实现这种解码的
package com.seara.socket.codec;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import com.seara.socket.message.ImageData;
import com.seara.socket.message.YHConstants;
/**
 * 接收图片数据,由于图片数据比较大,tcp是采用分段式发送,所有需要等所有数据接收完之后才能解码
 * 
 * 解码原理:首先读取服务器端发送数据的总长度length,然后与当前的buff中的数据长度matchLength比较,如果matchLength>=
 * length则认为数据发送完毕, 否則将当前的buff保存起来,在下次发送buff之时合并为一个buff,然后在按照以上条件判断
 * 
 * @author seara
 * 
 */
public class ImageDataDecoder extends CumulativeProtocolDecoder {
 private final AttributeKey CONTEXT = new AttributeKey(this.getClass(),
   "context");
 @Override
 protected boolean doDecode(IoSession session, IoBuffer buff,
   ProtocolDecoderOutput out) throws Exception {
  CharsetDecoder charset = Charset.forName("UTF-8").newDecoder();
  System.out.println("继续解码......." + buff.remaining());
  // 取出context
  Context ctx = this.getContext(session);// 将contex从session中取出
  int length = ctx.getLength();// 数据总长度
  IoBuffer buffer = ctx.getBuffer();// 保存数据的buffer
  int matchLength = ctx.getMatchLength();// 目前已经发送的数据的总长度
  if (0 == length) {// 第一次取值
   String yh = buff.getString(YHConstants.LENGTH, charset);
   length = buff.getInt();
   matchLength = buff.remaining();
   ctx.setYh(yh);
   ctx.setLength(length);
  } else {
   matchLength += buff.remaining();
  }
  ctx.setMatchLength(matchLength);
  if (buff.hasRemaining()) {// 如果buff中还有数据
   buffer.put(buff);// 添加到保存数据的buffer中
   if (matchLength >= length) {// 如果已经发送的数据的长度>=目标数据的长度,则进行解码
    byte[] b = new byte[length];
    // 一定要添加以下这一段,否则不会有任何数据,因为,在执行buffer.put(buff)时buffer的起始位置已经移动到最后,所有需要将buffer的起始位置移动到最开始
    buffer.flip();
    buffer.get(b);
    ImageData image = new ImageData(b);
    out.write(image);
    System.out.println("解码完成.......");
    return true;
   } else {
    ctx.setBuffer(buffer);
   }
  }
  return false;// 返回false时,解码器就不会执行解码,返回true是在解码完成
 }
 /**
  * 定义一个内部类,用来封转当前解码器中的一些公共数据,主要是用于大数据解析
  * 
  * @author seara
  * 
  */
 public class Context {
  public IoBuffer buffer;
  public int length = 0;
  public int matchLength = 0;
  public String yh = "";
  public Context() {
   this.buffer = IoBuffer.allocate(1024).setAutoExpand(true);
  }
  public int getMatchLength() {
   return matchLength;
  }
  public void setMatchLength(int matchLength) {
   this.matchLength = matchLength;
  }
  public IoBuffer getBuffer() {
   return buffer;
  }
  public void setBuffer(IoBuffer buffer) {
   this.buffer = buffer;
  }
  public int getLength() {
   return length;
  }
  public void setLength(int length) {
   this.length = length;
  }
  public String getYh() {
   return yh;
  }
  public void setYh(String yh) {
   this.yh = yh;
  }
 }
 public Context getContext(IoSession session) {
  Context ctx = (Context) session.getAttribute(CONTEXT);
  if (ctx == null) {
   ctx = new Context();
   session.setAttribute(CONTEXT, ctx);
  }
  return ctx;
 }
}
分享到:
评论

相关推荐

    mina传输对象的示例

    在标题和描述中提到的“mina传输对象的示例”指的是如何在Mina框架下处理和传输自定义的数据对象。Mina允许开发者通过事件驱动和异步I/O模型来高效地构建网络服务。 Mina的核心组件包括: 1. **Session**: 表示...

    sos.zip_SOS_mina

    总结起来,基于Apache Mina的Server实现涉及到的核心技术包括:利用Mina框架进行网络通信、内存自实现动态数组以优化内存管理、基本类型与字节数组的转化以适应网络数据传输,以及使用数据库连接池提高数据库访问...

    mina自定义编码器-固定位置指定消息的长度

    6. **返回编码结果**:最后,将编码后的字节数组返回给MINA框架,它会负责将这些字节发送到网络。 7. **配置MINA**:在你的MINA服务端或客户端配置中,注册你的自定义编码器,这样MINA在处理数据时会自动调用你的...

    mina学习基础-入门实例-传输定长报文(三)

    在"mina学习基础-入门实例-传输定长报文(三)"这个主题中,我们将深入探讨如何使用Mina实现定长报文的传输,并且利用Mina内置的SSL过滤器进行报文加密。 首先,让我们了解什么是定长报文。在通信协议中,定长报文是...

    Apache mina2学习笔记DEMO

    在创建自定义协议的DEMO中,开发者可能首先会定义一个ProtocolEncoder接口的实现,用来将应用层对象转换成ByteBuf(MINA中的字节数组表示)。接着,会实现ProtocolDecoder接口,负责将接收到的ByteBuf反序列化为应用...

    mina传递图片实例

    客户端会将图片数据转化为字节数组,然后通过MINA的`ByteBuffer`发送给服务器。 ```java public class MinaClient { private static final String SERVER_ADDRESS = "localhost"; private static final int PORT ...

    udp.rar_MINA udp_android mina UDP_mina_mina u

    解码器将接收到的原始字节数组转换为应用级别的对象,而编码器则反之。接下来,注册一个UDPDatagramHandler,它会在接收到数据包时被调用。 在MINA的过滤器链中,你可以添加自定义的过滤器来实现特定的功能,比如...

    mina和protobuf整合教程

    4. 在MINA服务端和客户端中使用生成的Java类:将数据序列化为字节数组,通过MINA的ByteBuffer进行传输;在接收端反序列化恢复数据。 5. 集成MINA事件处理器:在MINA的IoHandler或Filter中处理接收到的数据,进行反...

    mina解码器

    在这个场景中,"mina解码器"是指使用MINA框架来实现自定义的编码和解码逻辑,以处理网络数据的收发。 解码器(Decoder)和编码器(Encoder)是MINA框架中用于处理数据传输的核心组件。它们分别负责将接收到的原始...

    Mina上传文件

    1. **编码器(Encoder)**: 编码器负责将Java对象转化为字节数组。例如,对于文件上传,我们可以创建一个自定义的`FileEncoder`,它将文件内容转化为适合网络传输的格式,可能包括分割大文件成多个小块、添加头部...

    springboot整合mina

    // 将字节数组转换为业务对象 MyBusinessObject obj = deserialize(data); return obj; } // 序列化/反序列化方法... } ``` 最后,我们需要在处理器中注册这个自定义解码器。这通常在`MinaHandler`类中完成,...

    MinaUdp通信对象传输例子

    5. **序列化与反序列化**:在IoHandler中,我们需要将对象转换为字节数组进行发送,接收到字节流后反序列化回对象。 6. **绑定与连接**:服务端绑定到指定端口,客户端连接到服务端的IP和端口。 7. **数据交换**:...

    mina2.0相关jar包

    - **Buffer类**:MINA中的Buffer类提供了一种高效的方式来读写网络数据,它支持直接操作字节数组,避免了不必要的数据拷贝。 - **IoSession接口**:代表网络连接的会话,包含了连接状态、传输统计信息以及与特定...

    MinaDemo.zip SpringBoot集成Socket通讯

    例如,我们可以编写一个方法将十进制数转换为二进制,或者将十六进制字符串解析为字节数组,以便于数据的编码和解码。 总的来说,通过SpringBoot集成Mina框架,我们可以构建一个高性能的Socket服务器,处理客户端的...

    Routor.rar

    3. **编码/解码流程**:编码器会将业务对象转化为字节数组,解码器则负责将接收到的字节数组还原为业务对象。 4. **错误处理**:在网络通信中,数据可能会丢失或损坏,因此编解码器需要有容错机制,如错误检测和重...

    mina2.0用户指南

    本指南主要介绍了MINA 2.0的基本使用方法,包括NIO的介绍、MINA框架的核心组件以及与传统BIO(Blocking I/O)模式的对比。 NIO(New I/O),顾名思义,是Java提供的一个新I/O标准,它从Java 1.4版本开始引入,主要...

    springwith

    Spring Integration的Mina模块提供了一系列的转换器,如`ByteArrayStringDecoder`和`StringEncoder`,它们可以方便地将字节数组转换为字符串,或者反之。 在实际应用中,我们可能会遇到并发和性能问题。Spring和...

    dubbo介绍和使用

    - **序列化**:将 Java 对象转换成字节数组,以便在网络上传输。 - **传输**:通过特定的传输协议将数据包发送到目标节点。 - **交换**:实现请求与响应之间的交互过程。 - **RPC 模型**:定义了服务的发布、...

    基于NIO框架的TeeTime信息平台的设计与实现

    文章接着对阻塞I/O技术进行了详尽的分析,并在此基础上研究和学习了JDK1.4中提出的NIO技术,指出NIO技术相较于传统的流I/O技术,主要有两大改进点:一是提供了面向块的、非阻塞的I/O处理能力;二是让Java应用程序...

Global site tag (gtag.js) - Google Analytics