基于Mina框架的 socket网络通信
来源:互联网 发布:淘宝必须交保证金吗 编辑:程序博客网 时间:2024/04/28 18:40
一 Mina框架简介
1.1 Mina是apache基于socket nio的一套框架. 其因封装了socket网络通信 ,解耦了网络通信和具体的业务逻辑。让开发者
专注于具体的业务逻辑(数据)的处理.
1.2 Mina 框架的通信模型(主要的接口类) 简要介绍:
IoService接口: 连接网络的接口,对于服务器端IoAcceptor实现了这个接口。对于客户端IoConnector实现了这个接口
IoFilter(过滤器): 主要用于对数据(消息)进行编码和解码以及日志处理
IoHandler(处理器): 在这里接受IoFilter发送过来的数据进行业务处理返回数据给客户端。继承IoHandlerAdapter这个类
重写里面进行业务处理的方法。
1.3 Mina框架需要的jar包:
这里给出下载资源:http://download.csdn.net/detail/android_hdh/9601796
二 一个基于Mima框架的小Demo:MinaDemo
2.1 MinaDemo主要实现客户端发送消息给服务器端 服务器端打印客户端发来的消息。并统一回复消息“你好 Mina!”
2.2 服务器端的代码
2.2.1 IoHandler层代码:
package MinaService;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.session.IoSession;/** * 服务端实现 * IoHandler 业务处理层 * @author XuHao * */public class ServerHandler extends IoHandlerAdapter {/** * 当接口中其他方法抛出异常未被捕获时触发此方法 */@Overridepublic void exceptionCaught(IoSession session, Throwable cause)throws Exception {System.out.println("通信出错!");cause.printStackTrace();}/** * 当接收到客户端的请求信息后触发此方法 */@Overridepublic void messageReceived(IoSession session, Object message)throws Exception {String remsg = message.toString();System.out.println("messageReceived:" + remsg);session.write("你好 Mina!");}/** * 当连接空闲时触发此方法 */@Overridepublic void sessionIdle(IoSession session, IdleStatus status)throws Exception {System.out.println("IDLE:" + session.getIdleCount(status));}}2.2.2 IOFilter 层代码:
package MinaEncoding;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolEncoderOutput;import org.apache.mina.filter.codec.demux.MessageEncoder;/** * 编码类 (没有进行编码 直接进行了数据发送) * @author XuHao * */public class Encoder implements MessageEncoder<String>{public Encoder() {}/** * 没有编码 直接进行了数据的发送 */@Overridepublic void encode(IoSession session, String message, ProtocolEncoderOutput out)throws Exception {// 没有编码 模拟一下System.out.println("对数据进行编码");String value = (String)message;// message长度的一个bufIoBuffer buf = IoBuffer.allocate(value.getBytes().length);if (value != null){buf.put(value.trim().getBytes()); // 将message转成字节数组写入缓存里面}buf.flip(); // 反转缓存区out.write(buf);out.flush();}}
package MinaDecoding;import java.util.ArrayList;import java.util.List;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolDecoderOutput;import org.apache.mina.filter.codec.demux.MessageDecoder;import org.apache.mina.filter.codec.demux.MessageDecoderResult;/** * 解码类 * @author XuHao * */public class Decoder implements MessageDecoder {private byte[] r_curPkg = null; private int r_pos = -1; // 计数器static private final int PKG_SIZE_BYTES = 2; // 包长度public Decoder() {}/** * 判断接受的数据是否与协议相同 */@Overridepublic MessageDecoderResult decodable(IoSession session, IoBuffer in) {return MessageDecoderResult.OK;}/** * 解码接受到的数据包 */@Overridepublic MessageDecoderResult decode(IoSession session, IoBuffer in,ProtocolDecoderOutput out) throws Exception {List<String> list = new ArrayList<String>();while (in.remaining() >= PKG_SIZE_BYTES || (r_pos >= 0 && in.hasRemaining())) {// 循环接收包,4为一个整型,表示包长度b, 如果上一个包未接收完成时,继续接收 // 如果上个包已收完整,则创建新的包 if (r_pos == -1) { //得到下一个包的长度,长度不包括前两位,即包的长度=压缩位长度+数据位长度 int pkgLen = in.getShort(); //如果包长度小于0,那么此包错误,解码失败,返回。 if (pkgLen < 0) { return MessageDecoderResult.NOT_OK; } in.get(); r_curPkg = new byte[pkgLen-1]; //数组长度为数据长度 r_pos = 0; } int need = r_curPkg.length - r_pos; //需要读取的数据长度 int length = in.remaining();//缓冲区中可读的数据长度 if (length >= need) {// 可以把当前包读完整 in.get(r_curPkg, r_pos, need); // 复制缓冲区中的数据到r_curPkg中 // 处理接收到一个完整的包数据后,把包添加到池中,判断是否需要需要解压 byte[] data = r_curPkg; String str = new String(data); list.add(str); r_curPkg = null; r_pos = -1; } else { // 如果剩下的字节数,不够一个包则 int remainBytes = in.remaining(); in.get(r_curPkg, r_pos, remainBytes); r_pos += remainBytes; return MessageDecoderResult.NEED_DATA; } } for (String protocol : list) { out.write(protocol); } return MessageDecoderResult.OK; }@Overridepublic void finishDecode(IoSession session, ProtocolDecoderOutput out)throws Exception {}}
package MinaCoding;import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;import MinaDecoding.Decoder;import MinaEncoding.Encoder;/** * 编码工厂类 * @author XuHao * */public class CodecFactory extends DemuxingProtocolCodecFactory{public CodecFactory() {super.addMessageEncoder(String.class, Encoder.class);super.addMessageDecoder(Decoder.class);}}2.2.3 IoService层代码:
package MinaService;import java.io.IOException;import java.net.InetSocketAddress;import org.apache.mina.core.filterchain.IoFilter;import org.apache.mina.core.service.IoAcceptor;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.transport.socket.nio.NioSocketAcceptor;import MinaCoding.CodecFactory;/** * IoService层 * @author XuHao * */ public class MinaService {private static final int PORT = 9123;public static void main(String[] args) throws IOException {IoAcceptor acceptor = new NioSocketAcceptor(); // IoService的一个扩展接口// 编写过滤器// 日志记录acceptor.getFilterChain().addLast("logger", new LoggingFilter());// 设置编解码acceptor.getFilterChain().addLast( "codec", (IoFilter) new ProtocolCodecFilter(new CodecFactory()));// 将IoHandler注册到IoServiceacceptor.setHandler(new ServerHandler());acceptor.getSessionConfig().setReadBufferSize( 3 ); // 设置读取数据的缓存区大小为3个字节acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); // 设置读写通道均为10秒内无任何操作就进入空闲状态acceptor.bind( new InetSocketAddress(PORT) ); // 绑定socket端口地址}}
2.3 客户端代码:
package Client;import java.io.ByteArrayOutputStream;import java.net.InetSocketAddress;import java.nio.Buffer;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;/** * 客户端 * @author XuHao * */public class SocketClient {public static void main(String[] args) throws Exception {SocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("localhost",9123));byte[] bytes = "xuhao".getBytes(); // 这里就是发送的消息 为了简单明了 这里可以手动修改// 对数据包进行编码ByteBuffer buffer = ByteBuffer.allocate(bytes.length + 3);buffer.putShort((short)(bytes.length+1)); //包长度 buffer.put((byte)1);//闲置位 buffer.put(bytes);//数据 buffer.flip(); socketChannel.write(buffer); socketChannel.socket().shutdownOutput(); String obj = receive(socketChannel); System.out.println(obj);}/** * 接受服务器返回的消息 * @param socketChannel * @return * @throws Exception */private static String receive(SocketChannel socketChannel) throws Exception{ByteBuffer buffer = ByteBuffer.allocate(1024);ByteArrayOutputStream baos = new ByteArrayOutputStream();int size = 0;byte[] bytes = null;while((size = socketChannel.read(buffer))>=0){ buffer.flip(); bytes = new byte[size]; buffer.get(bytes); baos.write(bytes); buffer.clear(); } bytes = baos.toByteArray(); baos.close(); return new String(bytes);}}
0 0
- 基于Mina框架的 socket网络通信
- MINA网络通信框架
- mina作为socket通信框架
- Apache MINA网络通信框架
- socket通信框架mina使用详解
- 基于Java的socket网络通信
- Android中基于Socket的网络通信
- Android中基于Socket的网络通信
- Android基于Socket的网络通信
- java 基于TCP的Socket网络通信
- java 基于UDP的Socket网络通信
- 网络通信应用框架apache mina(一)
- [一]Mina入门实例-Mina网络通信框架
- 基于MINA框架快速开发网络应用程序
- 基于MINA框架快速开发网络应用程序
- 基于MINA框架快速开发网络应用程序
- 基于MINA 框架快速开发网络应用程序
- 基于MINA框架快速开发网络应用程序
- leetcode
- C++ 最小生成树(优先队列)
- JS第五天
- leetcode
- C#基础---浅谈XML读取以及简单的ORM实现
- 基于Mina框架的 socket网络通信
- leetcode
- 数据结构专题
- okhttp-OkGo(okhttp-util升级版)网络请求框架(二)
- 鸟哥的linux私房菜学习笔记《二十七》用户身份切换
- JS第六天
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(十二)阶段总结
- Maven安装以及环境配置(Windows)
- JAVA动态代理(proxy)实现和源码剖析