使用mina当服务器进行纯文本消息或多媒体消息加密会话

       首先,对于mina的基本使用这里就不多说了,之前已经转载了一篇很详细的说明。这次想分享的是使用mina框架自定义编解码器,实现发送纯文本和非纯文本消息,带PBE加密。

       首先定义要发送的信息包,之前一直想用mina进行图片语音,短视频的传送,把多媒体信息封装成一个类,纯文本文件封装成一个类。然后使用多路分离解码器,虽然这种方法可行,但是发送和接收都直接跳过了handler这层。到最后处理业务逻辑很不方便。

       然后尝试值使用一种格式的信息类,消息类型只有是纯文本或非纯文本的标识。一个String类型,真实发送时是发送JSON数据。然后一个byte数组。当是纯文本信息是,标识是'+',byte数组为null,这里不会造成new 一个信息类就会分配多余的内存。当时非纯文本信息时,标识是'-'。byte数组存放多媒体信息。

       接下来重要的环节就是编写编码器和解码器,思想很简单,根据发送的信息标识进行相应的编码,根据标识进行相应的解码。然后就是加密,这里用到的是PBE对称加密。加密时机是编码器编码时。解密就是在解码器解码时。加密速度我测试了一下。4.1M 加密:191ms 解密:198ms   15M  加密: 600ms    解密:570ms,应该还可以了。

       接下来附上代码:

1.信息类

       /**
 * symbol = '+' : 纯本文件
 * symbol = '-' : 非纯本文件
 * @author Administrator
 */
public class iMoMoMsg {
 public char symbol;//判断是否是纯文本文件
 public String msgJson;//包含图片详情的解释
 public byte[] msgBytes;//图片
}

 

2.编码类

package com.imomo_codecfactory;

import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;

import org.apache.commons.codec.binary.Base64;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

import com.imomo_msg.iMoMoMsg;
import com.security.PBE;

public class iMoMoEncoder extends ProtocolEncoderAdapter {
 CharsetEncoder encoder = Charset.forName("utf-8").newEncoder();
 // 纯文本发送格式:头标记(char) + 信息长度(int) +文本信信息(加密byte[])
 // 非纯文本发送格式:头标记(char) + 文字信息长度(int) + 文字信息(加密byte[]) + 多媒体信息长度(int) + 多媒体信息(加密byte[])
 @Override
 public void encode(IoSession session, Object msg, ProtocolEncoderOutput out)
   throws Exception {
  iMoMoMsg moMsg = (iMoMoMsg) msg;
  char symbol = moMsg.symbol;
  try {
   if (symbol == '+') {
    byte[] msgJsonByte = PBE.enCrypt(moMsg.msgJson.getBytes());//加密
    System.out.println("--发送文本信息   = " + moMsg.msgJson);
    int msgLen = msgJsonByte.length;
    // 2 :最开始的头部symbol,这里是'-+ ,4表示长度位
    IoBuffer io = IoBuffer.allocate(2 + 4 + msgLen).setAutoExpand(
      true);
    io.putChar(symbol);
    io.putInt(msgLen);
    io.put(msgJsonByte);
    io.flip();
    out.write(io);
   } else if (symbol == '-') {
    byte[] msgJsonByte = PBE.enCrypt(moMsg.msgJson.getBytes());//加密
    byte[] msgBytes = PBE.enCrypt(moMsg.msgBytes);
    System.out.println("--发送多媒体信息 = " + moMsg.msgJson
      + " msgBytesLen = " + msgBytes.length);
    int textLen = msgJsonByte.length;// 文字信息长度
    int msgBytesLen = msgBytes.length;// 图片长度
    IoBuffer io = IoBuffer.allocate(
      2 + 4 + 4 + textLen + msgBytesLen).setAutoExpand(true);
    io.putChar(symbol);
    io.putInt(textLen);
    io.put(msgJsonByte);
    io.putInt(msgBytesLen);
    io.put(msgBytes);
    io.flip();
    out.write(io);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

}

3.解码类

package com.imomo_codecfactory;

import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Date;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.demux.MessageDecoder;
import org.apache.mina.filter.codec.demux.MessageDecoderResult;

import com.imomo_msg.iMoMoMsg;
import com.security.PBE;

public class iMoMoDecoder extends CumulativeProtocolDecoder {
 CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();

 @Override
 protected boolean doDecode(IoSession session, IoBuffer in,
   ProtocolDecoderOutput out) throws Exception {
  iMoMoMsg moMsg = new iMoMoMsg();
  int pos = in.position();
  int remaining = in.remaining();
  try {
   // 判断长度,开头symbol 是char型
   if (remaining < 2) {
    in.position(pos);
    return false;
   }
   char symbol = in.getChar();// 相当于消费掉字节流
   moMsg.symbol = symbol;
   if (symbol == '+') {
    int msgJsonLen = 0;// msgJson长度
    // 判断是否够解析出的长度
    msgJsonLen = in.getInt();
    if (remaining - 2 < msgJsonLen || msgJsonLen < 0) {
     in.position(pos);
     return false;
    }
    byte[] temp = new byte[msgJsonLen];
    in.get(temp);//得到加密后byte数组
    moMsg.msgJson = new String(PBE.deCiphering(temp));
    out.write(moMsg);
   } else if (symbol == '-') {
    // 接收文本信息
    int msgJsonLen = 0;// msgJson长度
    int msgBytesLen = 0;// msgBytes长度
    msgJsonLen = in.getInt();
    if (remaining - 2 < msgJsonLen || msgJsonLen < 0) {
     in.position(pos);
     return false;
    }
    byte[] temp1 = new byte[msgJsonLen];
    in.get(temp1);//得到加密后byte数组
    moMsg.msgJson = new String(PBE.deCiphering(temp1));
    // 接收图片信息
    msgBytesLen = in.getInt();
    if (remaining - 2 - 4 - 4 - msgJsonLen < msgBytesLen
      || msgBytesLen < 0) {
     in.position(pos);
     return false;
    }
    byte[] temp2 = new byte[msgBytesLen];
    in.get(temp2);//得到加密后byte数组
    moMsg.msgBytes = PBE.deCiphering(temp2);
    out.write(moMsg);
   }
  } catch (Exception e) {
   e.printStackTrace();
   in.position(pos);
   return false;
  }
  return true;
 }
}

如果对编解码不熟的可以参考mina开发手册。

测试 发送15m的视频:

client handler类里:

@Override
 public void sessionOpened(IoSession session) throws Exception {
  iMoMoMsg moMoMsg = new iMoMoMsg();
  JSONObject textJson = new JSONObject();
  textJson.put("type", "login");
  textJson.put("id", "201513");
  textJson.put("pwd", "1234");
  moMoMsg.msgJson = textJson.toJSONString();
  moMoMsg.symbol = '+';
  session.write(moMoMsg);

  // 发送图片信息
  JSONObject multiJson = new JSONObject();
  multiJson.put("type", "pic");
  multiJson.put("sender", "001");
  multiJson.put("getter", "002");
  FileInputStream fileInputStream = new FileInputStream("f:\\moshou.avi");
  FileChannel channel = fileInputStream.getChannel();
  ByteBuffer bytebuffer = ByteBuffer.allocate((int) channel.size());
  bytebuffer.clear();
  channel.read(bytebuffer);
  iMoMoMsg moMoMsg2 = new iMoMoMsg();
  moMoMsg2.msgJson = multiJson.toJSONString();
  moMoMsg2.msgBytes = bytebuffer.array();
  moMoMsg2.symbol = '-';
  session.write(moMoMsg2);
  fileInputStream.close();
  channel.close();

 }

server handler里:

public void messageReceived(IoSession session, Object message)
   throws Exception {
  super.messageReceived(session, message);
  iMoMoMsg moMoMsg = (iMoMoMsg) message;
  if(moMoMsg.symbol == '+'){
   String msgJson = moMoMsg.msgJson;
   System.out.println("服务器 收到纯文本信息 : " + msgJson);
  } else if(moMoMsg.symbol == '-'){
   String msgJson = moMoMsg.msgJson;
   System.out.println("服务器 收到多媒体本信息 : " + msgJson + "多媒体信息长度" + moMoMsg.msgBytes.length);
   FileOutputStream fileout = new FileOutputStream("F:\\"
     + new Date().getMinutes() + "-.avi");
   FileChannel fc = fileout.getChannel();
   fileout.write(moMoMsg.msgBytes);
   fc.close();
   fileout.close();
  }
  
 }

控制台打印:

客户端:

 

本次加密用时 : 774
本次加密用时 : 651
--发送多媒体信息 = {"getter":"002","sender":"001","type":"pic"} msgBytesLen = 16174624

 

服务器:

本次解密用时 : 177

本次解密用时 : 597
服务器 收到多媒体本信息 : {"getter":"002","sender":"001","type":"pic"}多媒体信息长度16174616

 

从上可以看到:加密不管是对文本信息加密还是对多媒体文件加密,都比较耗时间,解密就相对较快。

 

具体工程:http://download.csdn.net/detail/u011102153/8615791

 

 

      

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值