mina框架入门

Apache Mina Server是一个网络通信应用框架,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架,MiNAk可以帮助我们开发高性能高扩展性的网络通信应用,Mina提供了事件驱动,异步操作的编程模型,学习本文档,需要你已掌握JAVA IO、JAVA NIO、JAVASocket、JAVA 线程及并发库(java.util.concurrent.*)的知识,mina同时提供了网络通信的server端,client端的封装,无论是那端,mina在整个网络通信中都处于如下的位置:可见mina的API将真正的网络通信与我们的应用程序隔离开来,你只需要开发你要发送接收的数据以及你的业务逻辑即可。同样的,无论是哪端,Mina 的执行流程如下所示:
(1.) IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。

(2.) IoProcessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分IoService与IoProcessor 两个功能接口。另外,IoProcessor 负责调用注册在IoService 上的过滤器,并在过滤器链之后调用IoHandler。

(3.) IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的encode 与decode是最为重要的、也是你在使用Mina 时最主要关注的地方。
(4.) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。

(2.)IoAcceptor:
这个接口是TCPServer 的接口,主要增加了void bind()监听端口、void unbind()解除对套接字的监听等方法。这里与传统的JAVA 中的ServerSocket 不同的是IoAcceptor 可以多次调用bind()方法(或者在一个方法中传入多个SocketAddress 参数)同时监听多个端口。

3.)IoConnector:
这个接口是TCPClient 的接口, 主要增加了ConnectFuture connect(SocketAddressremoteAddress,SocketAddress localAddress)方法,用于与Server 端建立连接,第二个参数如果不传递则使用本地的一个随机端口访问Server 端。这个方法是异步执行的,同样的,也可以同时连接多个服务端。

(6.)IoHandler:
这个接口是你编写业务逻辑的地方,从上面的示例代码可以看出,读取数据、发送数据基本都在这个接口总完成,这个实例是绑定到IoService 上的,有且只有一个实例(没有给一个IoService 注入一个IoHandler 实例会抛出异常)。它有如下几个方法:
A. void sessionCreated(IoSession session):
这个方法当一个Session 对象被创建的时候被调用。对于TCP 连接来说,连接被接受的时候调用,但要注意此时TCP 连接并未建立,此方法仅代表字面含义,也就是连接的对象IoSession 被创建完毕的时候,回调这个方法。对于UDP 来说,当有数据包收到的时候回调这个方法,因为UDP 是无连接的。
B. void sessionOpened(IoSession session):
这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP 来说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。对于UDP 来说,这个方法与sessionCreated()没什么区别,但是紧跟其后执行。如果你每隔一段时间,发送一些数据,那么sessionCreated()方法只会在第一次调用,但是sessionOpened()方法每次都会调用。
C. void sessionClosed(IoSession session) :
对于TCP 来说,连接被关闭时,调用这个方法。对于UDP 来说,IoSession 的close()方法被调用时才会毁掉这个方法。
D. void sessionIdle(IoSession session, IdleStatus status) :
这个方法在IoSession 的通道进入空闲状态时调用,对于UDP 协议来说,这个方法始终不会被调用。
E. void exceptionCaught(IoSession session, Throwable cause) :
这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭IoSession。
F. void messageReceived(IoSession session, Object message) :
接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message 是一个IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。通常我们都是会使用协议编解码器的, 就像上面的例子, 因为协议编解码器是
TextLineCodecFactory,所以我们可以强制转message 为String 类型。
G. void messageSent(IoSession session, Object message) :
当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,也就是说发送消息是不能用这个方法的。
发送消息的时机:
发送消息应该在sessionOpened()、messageReceived()方法中调用IoSession.write()方法完成。因为在sessionOpened()方法中,TCP 连接已经真正打开,同样的在messageReceived()方法TCP 连接也是打开状态,只不过两者的时机不同。sessionOpened()方法是在TCP 连接建立之后,接收到数据之前发送;messageReceived()方法是在接收到数据之后发送,你可以完成依据收到的内容是什么样子,决定发送什么样的数据。因为这个接口中的方法太多,因此通常使用适配器模式IoHandlerAdapter,覆盖你所感兴趣的方法即可。

5.过滤器:
前面我们看到了LoggingFilter、ProtocolCodecFilter 两个过滤器,一个负责日志输出,一个负责数据的编解码,通过最前面的Mina 执行流程图,在IoProcessor 与IoHandler 之间可以有很多的过滤器,这种设计方式为你提供可插拔似的扩展功能提供了非常便利的方式,目前的Apache CXF、Apache Struts2 中的拦截器也都是一样的设计思路。Mina 中的IoFilter 是单例的,这与CXF、Apache Struts2 没什么区别。IoService 实例上会绑定一个DefaultIoFilterChainBuilder 实例,DefaultIoFilterChainBuilder 会把使用内部的EntryImpl 类把所有的过滤器按照顺序连在一起,组成一个过滤器链。

client.java

public class Client {

	public static void main(String[] args) {
		//创建链接
		NioSocketConnector connector=new NioSocketConnector();
		DefaultIoFilterChainBuilder chain=connector.getFilterChain();
		//chain.addLast("myChain",new ProtocolCodecFilter(new TextLineCodecFactory()));
		chain.addLast("objectFilter",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
		//使用默认的过滤器一行一行的输出
		connector.setHandler((IoHandler) new MinaClientHandler());;
		//链接服务器
		ConnectFuture cf=connector.connect(new InetSocketAddress("localhost",9999));
		cf.awaitUninterruptibly();//等待链接成功
		Scanner input=new Scanner(System.in);
		while(true){
			/*System.out.println("请输入:");
			String info=input.nextLine();
			cf.getSession().write(info);//发送消息*/
			//以对象的方式传输数据
			Message msg=new Message();
			System.out.println("from:");
			msg.setFrom(input.nextLine());
			System.out.println("to:");
			msg.setTo(input.nextLine());
			System.out.println("info:");
			msg.setInfo(input.nextLine());
			msg.setType("send");
			cf.getSession().write(msg);
			
		}
		//等待链接服务器关闭,结束长链接
		//cf.getSession().getCloseFuture().awaitUninterruptibly();
		
		
		
	}

}
MinaClientHandler.java

public class MinaClientHandler extends IoHandlerAdapter {//消息处理器
public void sessionOpened(IoSession session)throws Exception{
	super.sessionOpened(session);
	System.out.println("sessionOpened");
}
public void sessionClosed(IoSession session)throws Exception{
	super.sessionClosed(session);
	System.out.println("sessionClosed");
}
public void messageReceived(IoSession session,Object message)throws Exception{
	super.messageReceived(session, message);
	//String msg=(String)message;
	Message msg=(Message)message;
	System.out.println(msg);
}
	public static void main(String[] args) {
		 
	}

}
Server.java

public class Server {

	public static void main(String[] args) {
		 //创建一个非阻塞的server端socket  NIO
		SocketAcceptor acceptor=new NioSocketAcceptor();
		DefaultIoFilterChainBuilder chain=acceptor.getFilterChain();
		//chain.addLast("myChain", new ProtocolCodecFilter(new TextLineCodecFactory()));
		//设定过滤器以对想为单位读取数据
		chain.addLast("objectFilter",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
		//设置一个过滤器一行一行的读取
		//设置服务器端的消息处理器
		acceptor.setHandler(new MinaServerHandler());
		int port=9999;
		try{
		acceptor.bind(new InetSocketAddress(port));//绑定端口服务器启动立即返回
		
		}catch(IOException e){
		e.printStackTrace();	
		}
		System.out.println("mina server running...,listening on"+port);
	}

}
MinaServerHandler.java

public class MinaServerHandler extends IoHandlerAdapter {
//服务器端的消息处理器
	 public static void main(String[] args) {
		 

	}
	public void sessionClosed(IoSession session) throws Exception {
		super.sessionClosed(session);
		System.out.println("client closed");
	}
	public void sessionOpened(IoSession session) throws Exception {
		super.sessionOpened(session);
		System.out.println("client"+session.getRemoteAddress());//获取远程的地址
	}
	public void messageReceived(IoSession session,Object message)throws Exception{
		super.messageReceived(session, message);
		//String msg=(String)message;//接收到的消息对象
		Message msg=(Message)message;
		System.out.println("收到客户端发来的消息"+msg);
		msg.setInfo("吃好吃的");
		session.write("echo:"+msg);//想客户端发送消息对象
	}
}
Message.java

public class Message implements Serializable{
private String from;
@Override
public String toString() {
	return "Message [from=" + from + ", to=" + to + ", type=" + type + ", info=" + info + "]";
}
public String getFrom() {
	return from;
}
public void setFrom(String from) {
	this.from = from;
}
public String getTo() {
	return to;
}
public void setTo(String to) {
	this.to = to;
}
public String getType() {
	return type;
}
public void setType(String type) {
	this.type = type;
}
public String getInfo() {
	return info;
}
public void setInfo(String info) {
	this.info = info;
}
private String to;
private String type;
private String info;
	public static void main(String[] args) {
		 
	}

}






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值