Mina是一个网络通信应用框架,可以实现TCP/IP、UDP/IP协议的通信,帮助我们开发高性能、高扩展的网络通信应用。下载地址:http://mina.apache.org/。
- 基本概念
SocketConnector/IoAcceptor:分别封装了服务器和客户端对象。
IoFilter:定义了一组拦截器。可以实现日志输出、数据的编解码等。主要用于数据的编解码,通过MessageDecoder和MessageEncoder实现。
IoHandler:负责编写业务逻辑。
- 代码示例
编码过滤器,在里面还要注册编码器和解码器
public class MessageCodecFactory extends DemuxingProtocolCodecFactory {
private MessageDecoder decoder;
private MessageEncoder<AbstrMessage> encoder;
public MessageCodecFactory(MessageDecoder decoder,
MessageEncoder<AbstrMessage> encoder) {
this.decoder = decoder;
this.encoder = encoder;
addMessageDecoder(this.decoder);
addMessageEncoder(AbstrMessage.class, this.encoder);
}
}
对象类,封装了网络传输的数据
public class AbstrMessage {
private byte[] messageBody;
public byte[] getMessageBody() {
return messageBody;
}
public void setMessageBody(byte[] messageBody) {
this.messageBody = messageBody;
}
}
编码器,将对象转换为byte流
public class MessEncoder implements MessageEncoder<AbstrMessage> {
private static final Logger logger = LoggerFactory.getLogger(MessEncoder.class);
public void encode(IoSession session, AbstrMessage message,
ProtocolEncoderOutput out) throws Exception {
IoBuffer buf = IoBuffer.allocate(100).setAutoExpand(true);
if(message.getMessageBody()!=null&&message.getMessageBody().length>0){
buf.put(message.getMessageBody());
}
buf.flip();
logger.info("发送消息:" + buf.getHexDump());
out.write(buf);
}
}
解码器,将byte流转换为对象
public class MessDecoder implements MessageDecoder {
private static final Logger logger = LoggerFactory.getLogger(MessDecoder.class);
public MessageDecoderResult decodable(IoSession session, IoBuffer in) {
return MessageDecoderResult.OK;
}
public MessageDecoderResult decode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) {
logger.info("收到消息:" + in.getHexDump());
AbstrMessage message = new AbstrMessage();
int bodyLen = 8;
byte[] bodyByte = new byte[bodyLen];
in.get(bodyByte);
message.setMessageBody(bodyByte);
out.write(message);
return MessageDecoderResult.OK;
}
public void finishDecode(IoSession session, ProtocolDecoderOutput out) {
}
}
Server端代码
// 创建一个非阻塞的server端的Socket
IoAcceptor acceptor = new NioSocketAcceptor();
// 设置过滤器(添加自带的编解码器)
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new MessageCodecFactory(
new MessDecoder(), new MessEncoder())));
// 绑定逻辑处理器
acceptor.setHandler(new ServerHandler());
try {
// 绑定端口
acceptor.bind(new InetSocketAddress(8888));
} catch (IOException e) {
e.printStackTrace();
}
Server端业务处理
public class ServerHandler extends IoHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(ServerHandler.class);
@Override
public void sessionCreated(IoSession session) {
logger.info("服务端与客户端"+session.getRemoteAddress()+"创建连接...");
}
@Override
public void sessionOpened(IoSession session) {
logger.info("服务端与客户端连接打开...");
}
@Override
public void sessionClosed(IoSession session) {
logger.info("客户端关闭连接...");
}
@Override
public void messageReceived(IoSession session, Object obj) {
AbstrMessage message = (AbstrMessage) obj;
session.write(message);
}
}
客户端调用代码
// Create TCP/IP connector.
SocketConnector connector = new NioSocketConnector();
// 设置过滤器(添加自带的编解码器)
connector.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new MessageCodecFactory(
new MessDecoder(), new MessEncoder())));
// 设定服务器端的消息处理器
connector.setHandler(new ClientHandler());
// 心跳时间间隔
connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
// 连结到服务器
connector.connect(new InetSocketAddress("127.0.0.1", 8888));
客户端业务处理
public class ClientHandler extends IoHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(ClientHandler.class);
@Override
public void sessionCreated(IoSession session) {
logger.info("服务端与客户端创建连接...");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) {
//心跳
logger.info("客户端发送心跳...");
}
@Override
public void sessionOpened(IoSession session) {
}
@Override
public void sessionClosed(IoSession session) {
logger.info("客户端关闭连接...");
}
@Override
public void messageReceived(IoSession session, Object obj) {
AbstrMessage message = (AbstrMessage)obj;
session.write(message);
}
}