您的位置:首页 > 其它

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

2015-04-21 21:43 351 查看
首先,对于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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐