文档章节

使用mina传输大字节数组

hejunbinlan
 hejunbinlan
发布于 2017/08/28 09:16
字数 993
阅读 24
收藏 0
点赞 0
评论 0

使用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;
 }
}

本文转载自:http://seara520.blog.163.com/blog/static/16812769820103214817781/

共有 人打赏支持
hejunbinlan
粉丝 40
博文 541
码字总数 21362
作品 0
浦东
高级程序员
Mina传输大数组,多路解码,粘包问题的处理

最近刚刚在做Java通信方面,初次接触mina,边根据网上查找的资料,结合自身的实际问题,作出了如下整理,希望能给类似问题的朋友帮助。 我的实际情况: 1,传递的业务数据种类很多,这就决定...

boonya
2016/06/05
721
0
使用 Apache MINA 2 开发网络应用

Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架。它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式。Apache MI...

红薯
2009/12/08
1K
0
JAVA NIO non-blocking模式实现高并发服务器

Java自1.4以后,加入了新IO特性,NIO. 号称new IO. NIO带来了non-blocking特性. 这篇文章主要讲的是如何使用NIO的网络新特性,来构建高性能非阻塞并发服务器. 文章基于个人理解,我也来搞搞NIO.,...

Mr&Cheng
2013/01/30
0
1
JAVA NIO non-blocking模式实现高并发服务器

Java自1.4以后,加入了新IO特性,NIO. 号称new IO. NIO带来了non-blocking特性. 这篇文章主要讲的是如何使用NIO的网络新特性,来构建高性能非阻塞并发服务器. 文章基于个人理解,我也来搞搞NIO.,...

xpbug
2013/01/10
0
4
MiNa 实现多人聊天室程序

开发环境: System:Windows JavaSDK:1.6 IDE:eclipse、MyEclipse 6.6 开发依赖库: Jdk1.4+、mina-core-2.0.4.jar、slf4j-api-1.5.11.jar、slf4j-log4j12-1.5.11.jar Email:hoojo_@126.......

ibm_hoojo
2012/08/01
0
0
NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

前言 NIO框架的流行,使得开发大并发、高性能的互联网服务端成为可能。这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2、而Netty的主要版本是Netty3和Netty4(Netty5已经被...

JackJiang-
2016/06/24
349
0
大小字节序的深入理解和鉴定系统字节序方法

最近在项目中的soket通信时,遇到了大小字节序问题和网络传输时的字节序问题,现在给大家整理一下,希望大家对字节序有个比较深入的了解,其实理解了就很简单的。 开始遇到的问题: 1、本地的...

沙米笔记
2016/03/26
649
3
mina2框架详解

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我...

小车车
2016/09/30
95
0
使用Mina2时,log日志能够打印出接收到的信息,但是messageReceived并未被调用,不

使用Mina2时,log日志能够打印出接收到的信息,但是messageReceived并未被调用,不知是什么回事? 2103844 [NioProcessor-1] INFO org.apache.mina.filter.logging.LoggingFilter - RECEIVED...

龙雪刚
2010/06/22
8.9K
13
Dubbo底层采用Socket进行通信详解(转)

由于Dubbo底层采用Socket进行通信,自己对通信理理论也不是很清楚,所以顺便把通信的知识也学习一下。 n 通信理论 计算机与外界的信息交换称为通信。基本的通信方法有并行通信和串行通信两种...

鈈哓锝
01/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Linux服务器下的HTTP抓包分析

说到抓包分析,最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了,但是有时候由于客户端开发人员(可能是第三方)知识欠缺或者其它一些原因,无法顺利的在客户端进行抓包分析,...

mylxsw
3分钟前
0
0
mybatis3-javaapi

sqlSessionFactoryBuilder->sqlSessionFactory->sqlSession<-rowbound<-resultHandler myBatis uses a Java enumeration wrapper for transaction isolation levels, called TransactionIsol......

writeademo
6分钟前
0
0
Java NIO:浅析I/O模型

也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念...

yzbty23
7分钟前
0
0
了解iOS消息推送一文就够:史上最全iOS Push技术详解

本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表。 1、引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ、微信等IM界面处于前台时,聊天消息和指令都会...

JackJiang-
8分钟前
0
0
Mysql汉子转拼音

update t_app_city SET CITY_NAME_BEGIN = ELT(INTERVAL(CONV(HEX(LEFT(CONVERT(CITY_NAME USING gbk),1)),16,10), 0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7, 0xBFA......

尘叙缘
10分钟前
0
0
大数据构建智慧城市“新引擎”,加速推进新旧动能转换

——“大数据与智慧城市”技术交流分享会——济南站召开 7月13日,“大数据携手智慧城市,助力山东新旧动能转换”技术交流分享会——济南站在山东信息通信技术研究院会议室成功举办,此次会议...

左手的倒影
12分钟前
2
0
tomcat 学习笔记之 Session管理

1、Catalina 通过一个 Session 管理器的组件来管理建立的Session 对象 该组件由 org.apache.catalina.Manager 接口表示 Session 管理器必须与一个 Context 关联 Session 管理器负责,创建、更...

职业搬砖20年
13分钟前
0
0
jquery获取input框的几种方式

//如何用jquery获取<input id="test" name="test" type="text"/>中输入的值?$(" #test ").val()$(" input[ name='test' ] ").val()$(" input[ type='text' ] ").val()$(" input[ ......

gulf
16分钟前
0
0
gradle的环境变量的配置

gradle的环境变量的配置 1.首先下载jdk,并且配置jdk的环境变量. 2.找到自己AS安装gradle的目录 我自己的目录为:F:\Android Studio3.1.3\gradle\gradle-4.4 创建环境变量:GRADLE_PATH: F:\A...

android-key
22分钟前
0
0
saltstack配置apache

1.相关配置 #vim /etc/salt/master //打开如下内容的注释 file_roots: base: - /srv/salt #mkdir /srv/salt #vim /srv/salt/top.sls base: 'slaver.test.com': - apache 注意:若换成 '*',则......

硅谷课堂
22分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部