您的位置:首页 > 理论基础 > 计算机网络

学习mina同步与异步网络通讯(二)——服务器端

2013-08-24 00:37 465 查看
写个服务器端,做测试。

服务器端与客户端最大的区别是使用IoAcceptor和IoHandler

核心代码:

package com.lele.test.mina.server.acceptor;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.lele.test.mina.server.acceptor.codec.CodecFactory;
import com.lele.test.mina.server.acceptor.handle.MinaServerHandler;

public class MinaAcceptor{

private int port = 1234;

// socket接收器
private SocketAcceptor acceptor;
private static MinaAcceptor minaAcceptor;
private SocketSessionConfig sessionConfig;
//单例模式
public static  MinaAcceptor getInstances(){
if (null == minaAcceptor) {
minaAcceptor = new MinaAcceptor();
}
return minaAcceptor;
}
protected MinaAcceptor() {
acceptor = new NioSocketAcceptor();
//此处的过滤器与客户端代码一样,使用自定义的CodecFactory
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new CodecFactory(false)));
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
sessionConfig = getAcceptor().getSessionConfig();
// 设置IoSession的read()方法为可用,默认为false,这行可以去掉,服务器端的read是被封装的,不需要定义IoSession,也不涉及到read(),应该是accptor内部实现了。
sessionConfig.setUseReadOperation(true);
//设置处理器
acceptor.setHandler(new MinaServerHandler());
try {
//注册端口。
acceptor.bind(new InetSocketAddress(port));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}

public SocketAcceptor getAcceptor() {
return acceptor;
}

public void setAcceptor(SocketAcceptor acceptor) {
this.acceptor = acceptor;
}

public SocketSessionConfig getSessionConfig() {
return sessionConfig;
}

public void setSessionConfig(SocketSessionConfig sessionConfig) {
this.sessionConfig = sessionConfig;
}

}
handler:

package com.lele.test.mina.server.acceptor.handle;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import com.lele.test.mina.server.acceptor.pojo.ApplyKeyRequest;
import com.lele.test.mina.server.acceptor.pojo.ApplyKeyResponse;

public class MinaServerHandler extends IoHandlerAdapter {

public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("session is created!");
}

public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("session is Opened!");
}

public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("session is Closed!");
}

public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
// TODO Auto-generated method stub

}

public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
// TODO Auto-generated method stub

}

public void messageReceived(IoSession session, Object message)
throws Exception {
if(message instanceof UserReq){

System.out.println(((UserRequest) message).getUsername());
}
//准备返回的数据!
UserRes a = new UserRes();
a.setSay("Mr.S say helloWorld!!!");
//此处与客户端的write一致,会调用filter进行转码,转成Byte[]
session.write(a);
}

public void messageSent(IoSession session, Object message) throws Exception {
// TODO Auto-generated method stub

}

}
接收完数据后,会自动关闭session。创建SESSION与打开session都是自动完成的。只要注册了handle~

查看一下SocketAcceptor的代码,继承自IoAcceptor~

几个接口,获取配置、IP端口等信息、是否暂停等。

在IoAcceptor中,有一个接口

IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress);


将会话绑定到客户端与服务端。怎么绑定的,没找到啊。。。

public void messageReceived(IoSession session, Object message)
throws Exception {
if(message instanceof UserReq){

System.out.println(((UserRequest) message).getUsername());
}
//准备返回的数据!
UserRes a = new UserRes();
a.setSay("Mr.S say helloWorld!!!");
//此处与客户端的write一致,会调用filter进行转码,转成Byte[]
session.write(a);
}
服务启动时加了过滤器,所以这面message读过来就已经解码成UserReq了

补充:

跟踪一下服务器端的线程,

MINA一共三种线程。

 第一类线程:NioSocketAcceptor 唯一。用于bind监听端口,bind一次创建一个。客户端发送请求时,将请求发送给第二类线程处理。

 第二类线程:Nioprocessor 处理客户端请求。每个请求1个线程。满了等待。acceptor = new NioSocketAcceptor(4);创建最大4个线程。handler中的sessionCreated

 第三类线程:处理业务逻辑的线程,使用过滤器添加。第二类线程接收请求后转给第三类请求处理。handler中的从sessionOpen到close。
如果不添加过滤器,那么业务处理将在第二类线程中完成。

acceptor = new NioSocketAcceptor(4);
//第三类线程
//acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));



使用可重用的线程池,当现有线程有可用则继续使用,如没有,创建新的线程。满了继续添加新的(PS:适合短连接。用完就销毁。提高性能啊!有机会测试一下。看最多能整多少个线程~)
Executors.newCachedThreadPool()
还有一种,创建固定个数的线程池,也是可重用的,只不过限制个数nThreads,满了会阻塞
newFixedThreadPool(int nThreads)

需要恶补一下线程方面的知识了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: