参考文章:http://blog.chinabyte.com/a/534099.html
传递对象的原因:个人理解:符合面向对象,服务器接收客户端消息,需要解析,处理,应答,如果传的是对象,可以把解析,处理,应答写在对象里,这么做,扩展性更好.
客户端
1 MinaClient.java
package com.nafio.client; 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.transport.socket.nio.NioSocketConnector; /** * @author nafio 2012-08-20 * mina传递对象客户端 */ public class MinaClient { //使用单例模式 private static MinaClient minaClient = null; //创建 TCP/IP connector NioSocketConnector connector = new NioSocketConnector(); //创建接收数据的过滤器 DefaultIoFilterChainBuilder chain = connector.getFilterChain(); //使用单例 //相关的IoHandlerAdapter继承类都采用了单实例模式 //在整个通信过程中做到对象session等实例的单一防止发生“所托非人”的现象//这个不是很理解? public static MinaClient getInstances() { if (null == minaClient) { minaClient = new MinaClient(); } return minaClient; } private MinaClient() { //设定这个过滤器将按对象读取数据 chain.addLast("myChin", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); connector.setHandler(ClientHandler.getInstances(connector));//by nafio用于彻底关闭客户端连接 //设定连接超时 connector.setConnectTimeout(30); //连接服务器 ConnectFuture cf = connector.connect(new InetSocketAddress("localhost", 8888)); } public static void main(String args[]) { MinaClient.getInstances(); } }
2 ClientHandler.java
package com.nafio.client; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.nafio.obj.TransferObj; /** * @author nafio 2012-08-20 * mina传递对象客户端 */ public class ClientHandler extends IoHandlerAdapter { private static ClientHandler minaClientHandler = null; NioSocketConnector connector;//by nafio用于彻底关闭客户端连接 public static ClientHandler getInstances(NioSocketConnector con) { if (null == minaClientHandler) { minaClientHandler = new ClientHandler(con); } return minaClientHandler; } private ClientHandler(NioSocketConnector con) { connector=con; } public void sessionOpened(IoSession session) throws Exception { //session.write("来自客户端:与服务端会话打开"); System.out.println("客户端:打开了与服务端的会话"); sendMsg(session); } //会话结束后触发 public void sessionClosed(IoSession session) { System.out.println("客户端:与服务端会话结束"); } //接到返回信息后触发 public void messageReceived(IoSession session, Object message)throws Exception { System.out.println("客户端:接收到服务端返回信息"); } //连接创建时触发 public void sessionCreated(IoSession session) throws Exception { super.sessionCreated(session); System.out.println("客户端:与服务端连接创建"); } //连接空闲是触发 public void sessionIdle(IoSession session, IdleStatus status) throws Exception { super.sessionIdle(session, status); System.out.println("客户端:连接空闲"); } //发送信息后触发 public void messageSent(IoSession arg0, Object arg1) throws Exception { //System.out.println("客户端:已向服务器发送-->"+(String)arg1); System.out.println("客户端:发送对象完毕"); arg0.close();//这里实际不能彻底关闭mina2.0需要connector.dispose()才能彻底关闭 connector.dispose();//不需要关闭去掉这两句就ok System.out.println("客户端:强行关闭连接"); } /** * 传送信息 * @param session * @throws Exception */ public void sendMsg(IoSession session) throws Exception{ TransferObj transferObj=new TransferObj(); transferObj.setDate("nafio_date"); session.write(transferObj); } public void exceptionCaught(IoSession session, Throwable cause) throws Exception { super.exceptionCaught(session, cause); } }
3 TransferObj.java
package com.nafio.obj; public class TransferObj implements java.io.Serializable{ private String date; public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
服务端
1 MinaServer.java
package com.nafio.server; 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.serialization.ObjectSerializationCodecFactory; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaServer { private static MinaServer minaServer = null; //创建一个非阻塞的Server端Socket private SocketAcceptor acceptor = new NioSocketAcceptor(); //创建接收数据的过滤器 private DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); private int bindPort = 8888; //单例 public static MinaServer getInstances() { if (null == minaServer) { minaServer = new MinaServer(); } return minaServer; } private MinaServer() { //设定这个过滤器将按对象读取数据 chain.addLast("myChin", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); //设定服务器端的消息处理器:一个MinaServerHandler对象, acceptor.setHandler(ServerHandler.getInstances()); try { //绑定端口,启动服务器 acceptor.bind(new InetSocketAddress(bindPort)); } catch (IOException e) { e.printStackTrace(); } System.out.println("服务端:监听端口--->" + bindPort); } public static void main(String[] args) throws Exception { MinaServer.getInstances(); } }
2 ServerHandler.java
package com.nafio.server; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import com.nafio.obj.TransferObj; //下面两种写法应该等同,不确定? //public class ServerHandler extends IoHandlerAdapter { public class ServerHandler extends IoFilterAdapter implements IoHandler { private static ServerHandler samplMinaServerHandler = null; public static ServerHandler getInstances() { if (null == samplMinaServerHandler) { samplMinaServerHandler = new ServerHandler(); } return samplMinaServerHandler; } private ServerHandler() { } public void sessionOpened(IoSession session) throws Exception { } public void sessionClosed(IoSession session) { } public void messageReceived(IoSession session, Object message)throws Exception { if (message instanceof TransferObj) { TransferObj obj = (TransferObj) message; System.out.println("服务端:收到客户端数据--->"+obj.getDate()); } } public void exceptionCaught(IoSession arg0, Throwable arg1)throws Exception { } public void messageSent(IoSession arg0, Object arg1) throws Exception { } public void sessionCreated(IoSession arg0) throws Exception { } public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception { } }
3 TransferObj.java(跟客户端相同,因为客户端和服务端要分开,所以这个类两个工程中都放一个)
彻底关闭mina客户端连接的方法
session.close();
java默认不赞成使用这个方法
这个方法使用后客户端实际还没彻底关闭
mina2.0彻底关闭用connector.dispose();
关于socket长短连接
通常的短连接操作步骤是:
连接→数据传输→关闭连接;
而长连接通常就是:
连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接;
这就要求长连接在没有数据通信时,定时发送数据包(心跳),以维持连接状态,短连接在没有数据传输时直接关闭就行了
所以mina默认应该就是长连接所以默认不关闭.