Mina处于中间层,它不关心底层网络数据如何传输,只负责接收底层数据,过滤并转换为Java对象提供给我们的应用程序,然后把应用程序响应值过滤并转换为底层识别的字节,提供给底层传输;
------总之:Mina是底层数据传输和用户应用程序交互的接口!
这个流程图不仅很直观的看出了Mina的工作流程,也涵盖了Mina的三个核心接口:IoService接口,IoFilter接口和IoHandler接口:
第一步. 创建服务对象(客户端或服务端) ---IoService接口实现
第二步. 数据过滤(编码解码等) ---IOFilter接口实现
第三步. 业务处理 ---IoHandler接口实现
Mina的精髓是IOFilter,它可以进行日志记录,信息过滤,编码解码等操作,把数据接收发送从业务层独立出来。
创建服务对象,则是把NIO繁琐的部分进行封装,提供简洁的接口。
业务处理是我们最关心的部分,跟普通的应用程序没任何分别。
package web.sample;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
//负责处理连接上来的客户机,即消息处理器
public class MinaServerHandler extends IoHandlerAdapter{
//客户端发送的消息到达时
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
// TODO Auto-generated method stub
String s = (String)message;
System.out.println("来自客户端的消息:"+s);
session.write(s);
}
//一个客户端关闭时
@Override
public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("one Client Disconnect");
}
//一个客户端接入时
@Override
public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("one Client Connection");
}
}
package web.sample;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class StartServer {
public static void main(String[] args) {
// 创建一个非阻塞的serever端socket,用Nio
SocketAcceptor acceptor = new NioSocketAcceptor();
// 创建接收数据的过滤器
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
// 设定这个过滤器规则(将一行一行读取数据)
chain.addLast("myChin", new ProtocolCodecFilter(new TextLineCodecFactory()));
// 设定服务器端的消息处理器:一个MinaServerHandler对象
acceptor.setHandler(new MinaServerHandler());
// 服务器端绑定的端口
int bindPort = 10000;
// 绑定端口,启动服务器
try {
acceptor.bind(new InetSocketAddress(bindPort));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Mina server is listing on:=" + bindPort);
}
}
1、使用telnet命令来和服务器进行连接,并发送消息,如图所示:
2、使用程序和服务器连接
package web.sample;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Logger;
/*
* 使用Socket创建客户端请求
*/
public class EchoClient01 {
// private Logger logger = Logger.getLogger(EchoClient01.class);
private String HOST = "localhost";
private int PORT = 10000;
private Socket socket;
public EchoClient01() throws IOException {
socket = new Socket(HOST, PORT);
}
public void talk() throws IOException {
try {
// 获得服务端响应信息的输入流
InputStream socketIn = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(socketIn));
// 给服务端发送信息的输出流
OutputStream socketOut = socket.getOutputStream();
PrintWriter pw = new PrintWriter(socketOut, true);
BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while ((msg = localReader.readLine()) != null) {
pw.println(msg);
// logger.info(br.readLine());
if (msg.equals("bye"))
break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
new EchoClient01().talk();
}
}
备注:public PrintWriter(OutputStream out,boolean autoFlush),通过现有的 OutputStream 创建新的 PrintWriter。此便捷构造方法创建必要的中间 OutputStreamWriter,后者使用默认字符编码将字符转换为字节。
如果只是创建使用这个PrintWriter(OutputStream out)构造方法,则服务器端是收到接收的信息的。