因公司需要做个电子秤自动称重系统,需要自定义协议实现,所以就用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

追求卓越,成功就会在不经意间追上你!

Mina自定义协议简单实现的更多相关文章

  1. 从零开始实现简单 RPC 框架 7:网络通信之自定义协议(粘包拆包、编解码)

    当 RPC 框架使用 Netty 通信时,实际上是将数据转化成 ByteBuf 的方式进行传输. 那如何转化呢?可不可以把 请求参数 或者 响应结果 直接无脑序列化成 byte 数组发出去? 答:直接 ...

  2. 利用Netty构建自定义协议的通信

    在复杂的网络世界中,各种应用之间通信需要依赖各种各样的协议,比如:HTTP,Telnet,FTP,SMTP等等. 在开发过程中,有时候我们需要构建一些适应自己业务的应用层协议,Netty作为一个非常优 ...

  3. C#综合揭秘——通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

  4. 【Win10 UWP】URI Scheme(二):自定义协议的处理和适用场景

    上一篇提到Windows Store协议的使用,其实Windows Store协议仅是系统内建的一种协议规则.我们也可以自己定义一套规范的URI-Scheme,除了可以给其他App调用外,本应用也可以 ...

  5. 【转】C#综合揭秘——通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

  6. Netty自定义协议解析原理与应用

    目前,大家都选择Netty做为游戏服务器框架网络通信的框架,而且目前也有很多优秀的产品是基于Netty开发的.它的稳定性,易用性和高效率性已得到广泛的认同.在游戏服务器开发中,选择netty一般就意味 ...

  7. 轨迹系列6——车载GPS对接方案汇总小结(809、自定义协议、前置库、WS)

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 最近在不同项目中对接了多个车载GPS厂商服务终端,绝大多数厂商 ...

  8. 采用自定义协议代替OCX组件

    事情起源:公司视频播放一直是采用的嵌入浏览器组件实现视频的预览回放等功能.这种实现方式要求客户使用IE浏览器. 最近上线项目使用Html 5开发,要求IE11.项目中使用了视频播放功能,如果全部升级到 ...

  9. 通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

随机推荐

  1. ModelForm

    这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,对,你没猜错,相信自己的英语水平. 先来一个简单的例子来看一下这个东西怎么用: 比如我们的数据库中有这样一 ...

  2. php 守护进程类

    最近个人项目中需要后台运行任务,之前一直是用nouhp & + 重定向输出 来后台跑任务,后来觉得不好维护原始数据,同时可能也没有直接操作进程那么稳吧(没验证).废话少说,来看分析. 首先,我 ...

  3. [译]ASP.NET Core 2.0 依赖注入

    问题 如何使用 ASP.NET Core 服务容器进行依赖注入? 答案 创建一个服务 public interface IGreetingService { string Greet(string t ...

  4. (七)php运算符

    一:算数运算符 +(加).-(减).*(成)./(除) %(取模,求余的意思) <?php $a=7/3; echo $a; //2.3333333333333.因为float类型的最大精度为1 ...

  5. [oracle 使用(1)] win7/10 下Oracle10g的安装与卸载

    1.安装前提 首先要确保你的电脑之前没有安装过,或者安装过但是已经卸载干净了.至于如何查看是否卸载干净可以看看我后面的Oracle卸载步骤. 2.Oracle的安装. 2.1.首先自己在Oracle官 ...

  6. 媲美jQuery的JS框架----AngularJS(二)

    前言 对于AngularJS什么,小编在这就不多做介绍了.大家可以看小编的上一篇博客. 言归正传,小编在上一篇博客中介绍了AngularJS中的指令.表达式还有非常实用的三种服务.接下来,带大家看一看 ...

  7. 2015ACM/ICPC亚洲区沈阳站 Pagodas

    Pagodas Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  8. 二叉搜索树 (BST) 的创建以及遍历

    二叉搜索树(Binary Search Tree) : 属于二叉树,其中每个节点都含有一个可以比较的键(如需要可以在键上关联值), 且每个节点的键都大于其左子树中的任意节点而小于右子树的任意节点的键. ...

  9. sql 1.1 1.1.1 1.10.1 排序

    解决思路:计算每位的权重,得到序号完整的权重值,使用权重值进行排序! 创建sql 函数如下: ALTER FUNCTION [dbo].[SequenceToOrderNum] ( @Sequence ...

  10. jquery实现抽奖小游戏

    在很多网站或游戏活动中我们都会看到有关抽奖的活动或界面: 下面我将给大家介绍下如何通过javascript来实现这样的一个抽奖功能,主要从下面三个步骤入手(文中着重介绍第三部分有关功能的实现): 1. ...