转自:http://hi.baidu.com/qinghua9/blog/item/28a819cedd575e31b600c8b4.html
其中用到的第三方JAR包有两个,分别是mina-core-2.0.0-M5.jar和slf4j-nop-1.5.6.jar
NIO的优点。何时才使用。当你需要比较多的并发,而且并发的需要做长连接时,传统的连续池可能会满足不了你的需求,必竟如果连接池维护过多的连接 时,对于虚拟机的要求比较高,但如果过少连接的话,阻塞的线程会让程序处理的非常慢,这时,你就可以考虑一下使用NIO框架MINA
下面是一个类似于HELLO WORLD的程序,相信熟悉SOCKET,看了马上就能上手MINA了。
客户端代码:
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class MinaClient
{
private static int PORT=8991;
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
System.out.println("开始机器连续服务器");
//创建TCP/IP的连接
NioSocketConnector connector=new NioSocketConnector();
//创建接收数据的过滤器
DefaultIoFilterChainBuilder chain=connector.getFilterChain();
/*
* 这里注意点:
* 1:TextLineCodecFactory设置这个过滤器一行一行(/r/n)的发送/读取数据
* 2.ObjectSerializationCodecFactory一般发送/接收的是对象等形象,以对象形式读取
*/
//chain.addLast("myChain",new ProtocolCodecFilter(new TextLineCodecFactory()));
chain.addLast("myChain",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
Message msg=new Message("TObject");
//设置处理的类
connector.setHandler(new MinaClientClient(msg));
//设置时间
connector.setConnectTimeoutMillis(300000);
//开始连接服务器
ConnectFuture cf=connector.connect(new InetSocketAddress("localhost",PORT));
//等待连接结束
cf.awaitUninterruptibly();
cf.getSession().getCloseFuture().awaitUninterruptibly();
connector.dispose();
}
}
客户端用MinaClientClient来处理发送的信息,MinaClientClient类必须继承IoHandlerAdapter,类似于Struts中处理action的类必须继承Action
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class MinaClientClient extends IoHandlerAdapter
{
public MinaClientClient()
{
}
private Object msg;
public MinaClientClient(Object message)
{
this.msg=message;
}
@Override
public void sessionOpened(IoSession session) throws Exception
{
System.out.println("我来了..");
session.write(msg);
}
@Override
public void sessionClosed(IoSession arg0) throws Exception
{
System.out.println("我走喽");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception
{
Message msg=(Message)message;
System.out.println("处理完的结果为"+msg.getMsgBody());
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
//session.write(strC);
// TODO Auto-generated method stub
//super.messageSent(session, message);
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
session.close(true);
}
}
服务端代码:
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChain;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
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 MainServer
{
//设置端口
public static int PORT=8991;
/**
* @param args
* @throws IOException
* @author jqh
*/
public static void main(String[] args) throws IOException
{
System.out.println("服务创建中");
//创建一个非阻塞的的server端socket,用NIO
SocketAcceptor acceptor=new NioSocketAcceptor();
//创建接收数据的过滤器
DefaultIoFilterChainBuilder chain=acceptor.getFilterChain();
/*
* 这里注意点:
* 1:TextLineCodecFactory设置这个过滤器一行一行(/r/n)的读取数据
* 2.ObjectSerializationCodecFactory一般接收的是对象等形象,以对象形式读取
*/
//chain.addLast("chain", new ProtocolCodecFilter(new TextLineCodecFactory()));
chain.addLast("chain", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
//设定服务器端消息处理器.:就是我们创建的TimeServerHandler对象
acceptor.setHandler(new TimeServerHandler());
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("MINS 服务器监听的服务端口为"+PORT);
}
}
类似于客户端,用于处理客户端请求的类为TimeServerHandler
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import com.dzkj.socketserver.minaclient.Message;
public class TimeServerHandler extends IoHandlerAdapter
{
/****
* session打开时,调用
*/
@Override
public void sessionOpened(IoSession session) throws Exception
{
System.out.println("incoming client ..."+session.getRemoteAddress());
}
/***
* 连接关才时调用
*/
@Override
public void sessionClosed(IoSession session) throws Exception
{
System.out.println("client close...........");
}
/**
* 如果出异常,就关闭session
*/
@Override
public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
{
cause.printStackTrace();
session.close(true);
}
/**
* 收到客户端信息时调用
*/
@Override
public void messageReceived( IoSession session, Object message ) throws Exception
{
System.out.println("in messageReceived");
Message msg = (Message) message;
System.out.println("begin send msg: " + msg.getMsgBody());
msg.setMsgBody("change it "+msg.getMsgBody());
session.write(msg);
System.out.println("Message written...");
}
/***
* 空闲时调用
*/
@Override
public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
{
System.out.println( "IDLE " + session.getIdleCount( status ));
}
}
对象类:
import java.io.Serializable;
public class Message implements Serializable {
private String msgBody;
public Message(String msgBody)
{
this.msgBody = msgBody;
}
public String getMsgBody() {
return msgBody;
}
public void setMsgBody(String msgBody) {
this.msgBody = msgBody;
}
}
先运行服务器---
再运行客户端.可得到结果:
客户端控制台:
开始机器连续服务器
我来了..
处理完的结果为change it TObject
我走喽
服务端控制台:
服务创建中
MINS 服务器监听的服务端口为8991
incoming client .../127.0.0.1:4685
in messageReceived
begin send msg: TObject
Message written...
client close...........
当然,服务端会一直监听8991端口。有客户端请求就会做处理,还有发送String对象就不写详细代码了。主要区别就是上面注释提到的部分要改一下,然后直接写String过去即可。
还有要注意的是,传送Object时,对象一定要实现Serializable。反序例化一般比较严谨的操作。别忘了