【承上文
http://unbounder.iteye.com/blog/481396】
3 MINA
项目主页:http://mina.apache.org/
闲话不说,上代码
public class Server extends Thread {
private static final int PORT = 23;
public void run() {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new TestHandler());
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new TextLineCodecFactory()));
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
try {
acceptor.bind(new InetSocketAddress(PORT));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("The ProjectServer start on port: " + PORT);
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
public class TestHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
session.close(true);
}
@Override
public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("the new session is connecting");
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
String str = message.toString();
System.out.println(str);
}
}
最简单的一个mina服务器实现,telnet就可以看到效果。
稍微解释一下
mina的实现主要在于给IoAcceptor增加过滤器
new ProtocolCodecFilter(new TextLineCodecFactory()):这是一个解码器,可以自己实现ProtocolCodecFactory接口编写特定的解码器。不过注意一下,解码器必须和编码器同时使用,服务器端实现特定解码器的同时需要客户端应用特定编码。
常用过滤器还有日志LoggingFilter()等,具体可以查看api。
这里笔者想说的是对于一般的socket服务器,可能客户端并不会使用mina,譬如j2me或者干脆是一个c++的socket请求,此时我们上面的demo将毫无作用,具体来说就是解码过滤器失效。在实际应用中,我们一般是这样的处理的:
public class Server extends Thread {
private static final int PORT = 11001;
public void run() {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new TestHandler());
acceptor.getFilterChain().addLast("ddd", new StreamWriteFilter());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
try {
acceptor.bind(new InetSocketAddress(PORT));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("The ProjectServer start on port: " + PORT);
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
注意我们并没有再使用
acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory()));
而是
acceptor.getFilterChain().addLast("ddd", new StreamWriteFilter());
这个过滤器是直接对写入流操作,即原始的数据流
handler端代码也要修改
public class TestHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
session.close(true);
}
@Override
public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("the new session is connecting");
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
IoBuffer buffer=(IoBuffer)message;
ByteBuffer bf= buffer.buf();
byte[] tempBuffer=new byte[bf.limit()];
bf.get(tempBuffer);
String str=new String(tempBuffer);
System.out.println(str);
}
}
注意这段
IoBuffer buffer=(IoBuffer)message;
ByteBuffer bf= buffer.buf();
byte[] tempBuffer=new byte[bf.limit()];
bf.get(tempBuffer);
String str=new String(tempBuffer);
System.out.println(str);
将原始的数据流还原为字符串,如果传输协议不是字符串而是byte数组,就直接对tempBuffer操作即可。
附件中为mina的jar包和所以来的slf4j的jar包,欢迎下载。