因公司需要做个电子秤自动称重系统,需要自定义协议实现,所以就用Mina简单实现了一下,因为比较简单,就直接上代码。有时间的话改成Netty版
服务端
package net.heartma.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
import net.heartma.protocol.CustomProtocolCodecFactory;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
/**
* 服务端
* @author heartma
*
*/
public class BalanceServer {
private static SocketAcceptor acceptor;
private static DefaultIoFilterChainBuilder filter;
private static SocketSessionConfig config;
public static Logger logger = Logger.getLogger("BalanceServer");
private static Executor threadPool = Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// 1、创建服务器端监听
acceptor = new NioSocketAcceptor();
// 2、添加日志过滤和编码过滤
filter = acceptor.getFilterChain();
filter.addLast("threadPool", new ExecutorFilter(threadPool));
filter.addLast("logger", new LoggingFilter());
// ----编码过滤:将二进制或者协议相关数据转换成一个对象。TextLine工厂类可以处理基于文字的信息
filter.addLast("codec", new ProtocolCodecFilter(new CustomProtocolCodecFactory()));
// 3、绑定handler到acceptor
acceptor.setHandler(new BalanceServerHandler());
// 4、设置socket属性
// 获取socket的连接参数
config = acceptor.getSessionConfig();
// 设置socket的缓冲区大小为2M
config.setReadBufferSize(2048);
/**
* @params IdleStatus arg0 :在未成为idle状态前应该关心的状态(READ_IDLE或者WRITE_IDLE)
* @params @params IdleStatus arg1 : 变成IDLE状态所需要的时间(超时时间)
*
* 如果session持续idle的时间等于arg1时,将会触发handler中的sessionIdle方法
*/
// 设置空闲状态持续时间:1、这里的状态可以自己设置成只为读取设置空闲状态持续时间,只为写入设置空闲状态等待时间,或者为两者都设置空闲状态等待时间。后面的时间是两次触发handler中的sessionIdel方法的间隔时间。
config.setIdleTime(IdleStatus.BOTH_IDLE, 10);
try {
// 为服务器socket绑定端口
acceptor.bind(new InetSocketAddress(8081));
logger.info("服务已经启动... ...");
} catch (IOException e) {
logger.info("服务启动异常 :");
e.printStackTrace();
}
}
}
服务端Handler
package net.heartma.server;
import net.heartma.pojo.Message;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
/**
* 服务端Handler
* @author heartma
*
*/
public class BalanceServerHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession ioSession, Throwable e)
throws Exception {
System.out.println("exceptionCaught");
}
@Override
public void messageReceived(IoSession ioSession, Object obj) throws Exception {
System.out.println("messageReceived");
Message message = (Message)obj;
System.out.println("服务器端接收到的消息:" +message);
}
@Override
public void messageSent(IoSession ioSession, Object obj) throws Exception {
System.out.println("messageSent");
}
@Override
public void sessionClosed(IoSession ioSession) throws Exception {
System.out.println("sessionClosed");
}
@Override
public void sessionCreated(IoSession ioSession) throws Exception {
System.out.println("sessionCreated");
}
@Override
public void sessionIdle(IoSession ioSession, IdleStatus arg1) throws Exception {
System.out.println("sessionIdle");
}
@Override
public void sessionOpened(IoSession ioSession) throws Exception {
System.out.println("sessionOpened");
}
}
客户端
23230E363932383834363630333738370D303030302E3434 为定义的协议报文
package net.heartma.client;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import net.heartma.protocol.CustomProtocolCodecFactory;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
/**
* Mina客户端
* @author Administrator
*
*/
public class BalanceClient {
public static void main(String[] args) {
// 创建客户端连接器 基于tcp/ip
NioSocketConnector connector = new NioSocketConnector();
// 连接的地址和端口
SocketAddress address = new InetSocketAddress("localhost",8081);
// 获取过滤器链
DefaultIoFilterChainBuilder chain = connector.getFilterChain();
// 配置日志过滤器和自定义编解码器
chain.addLast("logger", new LoggingFilter());
chain.addLast("mycodec",new ProtocolCodecFilter(new CustomProtocolCodecFactory()));
// 添加处理器
connector.setHandler(new BalanceClientHandler());
// 连接到服务器
ConnectFuture future = connector.connect(address);
// 等待连接创建完成
future.awaitUninterruptibly();
// 会话创建后发送消息到服务器
future.getSession().write("23230E363932383834363630333738370D303030302E3434");
// 等待28000毫秒后连接断开
future.getSession().getCloseFuture().awaitUninterruptibly(28000);
// 关闭连接
connector.dispose();
}
}
客户端Handler
package net.heartma.client;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
/**
* 客户端Handler
* @author heartma
*
*/
public class BalanceClientHandler extends IoHandlerAdapter {
public void exceptionCaught(IoSession ioSession, Throwable e)
throws Exception {
System.out.println("exceptionCaught");
}
public void messageReceived(IoSession ioSession, Object obj) throws Exception {
System.out.println("messageReceived");
}
public void messageSent(IoSession ioSession, Object obj) throws Exception {
System.out.println("客户端发送消息...");
//super.messageSent(ioSession, obj);
}
public void sessionClosed(IoSession ioSession) throws Exception {
System.out.println("sessionClosed");
}
public void sessionCreated(IoSession ioSession) throws Exception {
System.out.println("sessionCreated");
}
public void sessionIdle(IoSession ioSession, IdleStatus idle) throws Exception {
System.out.println("sessionIdle");
}
public void sessionOpened(IoSession ioSession) throws Exception {
System.out.println("sessionOpened");
}
}
实体消息体Message
package net.heartma.pojo;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
/**
* 定义消息体属性
* @author heartma
*
*/
public class Message {
private String header; //头
private int length; //卡号长度
private String card; //卡号
private double weight; //重量
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getCard() {
return card;
}
public void setCard(String card) {
this.card = card;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
/**
* 解析字节数组
* @param messageBytes
*/
public final boolean ReadFromBytes(byte[] messageBytes) {
//获取头部
byte[] head = new byte[2];
System.arraycopy(messageBytes, 0, head, 0,2);
setHeader(new String(head));
//获取长度
byte[] len = new byte[1];
System.arraycopy(messageBytes, 2, len, 0,1);
setLength(len[0]);
//判断卡号长度是否为0,为0则说明为心跳信息,否则为真实数据
if((int)len[0]>0){
//卡号解析
byte[] cardDest = new byte[len[0]];
System.arraycopy(messageBytes, 3, cardDest, 0,len[0]);
setCard(new String(cardDest));
byte[] weightDest = new byte[7];
System.arraycopy(messageBytes, 3+length, weightDest, 0,7);
setWeight(Double.parseDouble(new String(weightDest)));
return true;
}
return false;
}
@Override
public String toString() {
return "Message [header=" + header + ", length=" + length + ", card="
+ card + ", weight=" + weight + "]";
}
}
自定义协议工厂类
package net.heartma.protocol;
import java.nio.charset.Charset;
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 heartma
*/
public class CustomProtocolCodecFactory implements ProtocolCodecFactory{
private final CustomProtocolDecoder decoder;
private final CustomProtocolEncoder encoder;
public CustomProtocolCodecFactory(){
this.decoder = new CustomProtocolDecoder(Charset.forName("utf-8"));
this.encoder = new CustomProtocolEncoder(Charset.forName("utf-8"));
}
@Override
public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception {
return encoder;
}
}
自定义协议编码
package net.heartma.protocol;
import java.nio.charset.Charset;
import net.heartma.tools.ByteUtil;
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;
/**
* 自定义协议编码
* @author heartma
*/
public class CustomProtocolEncoder extends ProtocolEncoderAdapter {
private Charset charset;
public CustomProtocolEncoder(Charset charset) {
this.charset = charset;
}
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
byte[] hexStrToByte = ByteUtil.hexStr2ByteArray(message.toString());
IoBuffer buf = IoBuffer.allocate(hexStrToByte.length).setAutoExpand(false);
//byte[] content = Tools.HexString2Bytes(message.toString());
buf.put(hexStrToByte);
buf.flip();
out.write(buf);
out.flush();
buf.free();
}
}
自定义协议解码
package net.heartma.protocol;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import net.heartma.pojo.Message;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/**
* 自定义协议解码
* @author heartma
*/
public class CustomProtocolDecoder extends ProtocolDecoderAdapter {
private CharsetDecoder decoder;
public CustomProtocolDecoder(Charset charset){
this.decoder = charset.newDecoder();
}
@Override
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
int limit = in.limit();
byte[] bytes = new byte[limit];
in.get(bytes);
Message message = new Message();
message.ReadFromBytes(bytes);
out.write(message);
}
}
代码下载:
http://download.csdn.net/download/cos18661062156/10141901
追求卓越,成功就会在不经意间追上你!