用到了mina,自己记录下,用到了以前文章
编码 解码的例子
http://blog.youkuaiyun.com/jbgtwang/article/details/26266309
http://blog.youkuaiyun.com/jbgtwang/article/details/26261643
messageReceivce中字符还原成字符串的例子。
http://m.blog.youkuaiyun.com/eddle/article/details/6895550
字节截取的例子
http://blog.youkuaiyun.com/u010277446/article/details/52459613
- /**
- * 将byte[]转换成string
- * @param butBuffer
- */
- public static String byteToString(byte [] b)
- {
- StringBuffer stringBuffer = new StringBuffer();
- for (int i = 0; i < b.length; i++)
- {
- stringBuffer.append((char) b [i]);
- }
- return stringBuffer.toString();
- }
- /**
- * 将bytebuffer转换成string
- * @param str
- */
- public static IoBuffer stringToIoBuffer(String str)
- {
- byte bt[] = str.getBytes();
- IoBuffer ioBuffer = IoBuffer.allocate(bt.length);
- ioBuffer.put(bt, 0, bt.length);
- ioBuffer.flip();
- return ioBuffer;
- }
- /**
- * 将IoBuffer转换成string
- * @param str
- */
- public static IoBuffer byteToIoBuffer(byte [] bt,int length)
- {
- IoBuffer ioBuffer = IoBuffer.allocate(length);
- ioBuffer.put(bt, 0, length);
- ioBuffer.flip();
- return ioBuffer;
- }
- /**
- * 将IoBuffer转换成byte
- * @param str
- */
- public static byte [] ioBufferToByte(Object message)
- {
- if (!(message instanceof IoBuffer))
- {
- return null;
- }
- IoBuffer ioBuffer = (IoBuffer)message;
- byte[] b = new byte[ioBuffer.limit()];
- ioBuffer.get(b);
- return b;
- }
- /**
- * 将IoBuffer转换成string
- * @param butBuffer
- */
- public static String ioBufferToString(Object message)
- {
- if (!(message instanceof IoBuffer))
- {
- return "";
- }
- IoBuffer ioBuffer = (IoBuffer) message;
- byte[] b = new byte [ioBuffer.limit()];
- ioBuffer.get(b);
- StringBuffer stringBuffer = new StringBuffer();
- for (int i = 0; i < b.length; i++)
- {
- stringBuffer.append((char) b [i]);
- }
- return stringBuffer.toString();
- }
- public static byte[] subBytes(byte[] src, int begin, int count) {
- byte[] bs = new byte[count];
- System.arraycopy(src, begin, bs, 0, count);
- return bs;
- }
我们在自定义传输协议时,通常都是采用字节数组的方式进行传送,如何正确接收和解码byte数组?
假设我们自定义了传输协议: 字节数组的前4个字节是要传输的数据长度,后面跟数据。我们用mina可以这样处理
1.自定义编码器ByteArrayEncoder.java
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/**
* 编码器将数据直接发出去(不做处理)
*/
public class ByteArrayEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
out.write(message);
out.flush();
}
}
2.自定义解码器(确保能读取到完整的包)
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 com.talkweb.meeting.tools.IntByteConvert;
public class ByteArrayDecoder extends CumulativeProtocolDecoder {
@Override
public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
if(in.remaining() > 4){//前4字节是包头
//标记当前position的快照标记mark,以便后继的reset操作能恢复position位置
in.mark();
byte[] l = new byte[4];
in.get(l);
//包体数据长度
int len = MyTools.bytes2int(l);//将byte转成int
//注意上面的get操作会导致下面的remaining()值发生变化
if(in.remaining() < len){
//如果消息内容不够,则重置恢复position位置到操作前,进入下一轮, 接收新数据,以拼凑成完整数据
in.reset();
return false;
}else{
//消息内容足够
in.reset();//重置恢复position位置到操作前
int sumlen = 4+len;//总长 = 包头+包体
byte[] packArr = new byte[sumlen];
in.get(packArr, 0 , sumlen);
IoBuffer buffer = IoBuffer.allocate(sumlen);
buffer.put(packArr);
buffer.flip();
out.write(buffer);
buffer.free();
if(in.remaining() > 0){//如果读取一个完整包内容后还粘了包,就让父类再调用一次,进行下一次解析
return true;
}
}
}
return false;//处理成功,让父类进行接收下个包
}
}
3.编解码工厂类
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
/**
* @author BruceYang
*
*/
public class ByteArrayCodecFactory implements ProtocolCodecFactory {
private ByteArrayDecoder decoder;
private ByteArrayEncoder encoder;
public ByteArrayCodecFactory() {
encoder = new ByteArrayEncoder();
decoder = new ByteArrayDecoder();
}
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
4.调用编解码工厂进行编解码
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("mycoder", new ProtocolCodecFilter(new ByteArrayCodecFactory()));
假设我们自定义了传输协议: 字节数组的前4个字节是要传输的数据长度,后面跟数据。我们用mina可以这样处理
1.自定义编码器ByteArrayEncoder.java
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/**
* 编码器将数据直接发出去(不做处理)
*/
public class ByteArrayEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
out.write(message);
out.flush();
}
}
2.自定义解码器(确保能读取到完整的包)
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 com.talkweb.meeting.tools.IntByteConvert;
public class ByteArrayDecoder extends CumulativeProtocolDecoder {
@Override
public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
if(in.remaining() > 4){//前4字节是包头
//标记当前position的快照标记mark,以便后继的reset操作能恢复position位置
in.mark();
byte[] l = new byte[4];
in.get(l);
//包体数据长度
int len = MyTools.bytes2int(l);//将byte转成int
//注意上面的get操作会导致下面的remaining()值发生变化
if(in.remaining() < len){
//如果消息内容不够,则重置恢复position位置到操作前,进入下一轮, 接收新数据,以拼凑成完整数据
in.reset();
return false;
}else{
//消息内容足够
in.reset();//重置恢复position位置到操作前
int sumlen = 4+len;//总长 = 包头+包体
byte[] packArr = new byte[sumlen];
in.get(packArr, 0 , sumlen);
IoBuffer buffer = IoBuffer.allocate(sumlen);
buffer.put(packArr);
buffer.flip();
out.write(buffer);
buffer.free();
if(in.remaining() > 0){//如果读取一个完整包内容后还粘了包,就让父类再调用一次,进行下一次解析
return true;
}
}
}
return false;//处理成功,让父类进行接收下个包
}
}
3.编解码工厂类
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
/**
* @author BruceYang
*
*/
public class ByteArrayCodecFactory implements ProtocolCodecFactory {
private ByteArrayDecoder decoder;
private ByteArrayEncoder encoder;
public ByteArrayCodecFactory() {
encoder = new ByteArrayEncoder();
decoder = new ByteArrayDecoder();
}
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
4.调用编解码工厂进行编解码
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("mycoder", new ProtocolCodecFilter(new ByteArrayCodecFactory()));