常见NIO开源框架(MINA、xSocket)学习
2013-08-01 18:00
447 查看
基于io包的阻塞式socket通信代码简单,在连接数很少的情况下是一个不错的选择。不过实际应用中一个socket服务器采用传统的阻塞式socket方式通信可能会是一场灾难,一路socket同时进行读写操作可能就需要两条线程,如果需要并发一百路socket(这个量其实很小了),可能就是两百条线程,大概几分钟后cpu占用率就是高居不下了。
基于原生nio的socket通信时一种很好的解决方案,基于事件的通知模式使得多并发时不用维持高数量的线程,高并发的socket服务器的java实现成为现实。不过原生nio代码十分复杂,无论编写还是修改都是一件头疼的事。“屏蔽底层的繁琐工作,让程序员将注意力集中于业务逻辑本身”,有需求就有生产力进步,于是各式各样的nio框架涌现而出,而笔者使用到的是其中最常见的两种:xSocket和MINA。
1 xsocket框架
官网:http://xsocket.sourceforge.net/
xSocket是一套非常简洁的nio框架,利用这套框架,你可以在完全不了解nio的情况下设计出高并发的socket服务器。
server端代码:
Java代码
public class ProjectServer extends Thread {
private static final int PORT=9099;
public void run() {
IServer srv = null;
try {
//建立handler
srv = new Server(PORT, new ProjectHandle());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//服务器运行
srv.run();
System.out.println("The ProjectServer start on port: "+PORT);
}
public static void main(String[] args) {
ProjectServer projectServer = new ProjectServer();
projectServer.start();
}
}
handler代码
Java代码
public class ProjectHandle implements IDataHandler, IConnectHandler,
IDisconnectHandler {
/* 处理连接建立事件 */
@Override
public boolean onConnect(INonBlockingConnection nbc) throws IOException,
BufferUnderflowException, MaxReadSizeExceededException {
// TODO Auto-generated method stub
System.out.println(nbc.getId() + "is connect!");
return true;
}
/* 处理连接断开事件 */
@Override
public boolean onDisconnect(INonBlockingConnection nbc) throws IOException {
// TODO Auto-generated method stub
System.out.println(nbc.getId() + "is disconnect!");
return true;
}
/* 处理接受数据事件 */
@Override
public boolean onData(INonBlockingConnection nbc) throws IOException,
BufferUnderflowException, ClosedChannelException,
MaxReadSizeExceededException {
// TODO Auto-generated method stub
String str = nbc.readStringByDelimiter("\0");
System.out.println(str);
return true;
}
}
这里我们以"\0"为间隔读取数据,xSocket还提供按照长度读取以及全部读取到一个ByteBuffer几种读取数据的方式,如果传递过程中采取byte数组格式,在接受数据时还可以使用xSocket自带的工具类DataConverter进行转化。譬如接收数据时如此操作:
Java代码
ByteBuffer copyBuffer = ByteBuffer.allocate(20000);
nbc.read(copyBuffer);
copyBuffer.flip();
String str = DataConverter.toString(copyBuffer, "utf-8");
就可以将二进制格式的传输内容还原为原始字符串了。
需要说明的是虽然xSocket代码简单、开发快捷,但是由于太“上层”了,所以很多地方不利于coder自己控制。譬如socket通信中一个很常见的“半包连包”问题用xsocket处理起来就会很麻烦,而且如果传输协议是经过特殊设计的,xsocket也无法像mina那样自己编写解码器。当然如果你不是特别计较这些方面,那么非常适于上手的xSocket就是适合你的nio框架。
另,附件中为xsocket所需要的jar包,下载后直接加载项目中即可使用。
3 MINA
项目主页:http://mina.apache.org/
闲话不说,上代码
Java代码
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();
}
}
Java代码
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将毫无作用,具体来说就是解码过滤器失效。在实际应用中,我们一般是这样的处理的:
Java代码
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端代码也要修改
Java代码
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);
}
}
注意这段
Java代码
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包,欢迎下载。
slf4j-api-1.5.3.jar (19.7 KB)
下载次数: 66
mina-core-2.0.0-M4.jar (619.8 KB)
下载次数: 81
slf4j-simple-1.5.3.jar (7.3 KB)
下载次数: 62
基于原生nio的socket通信时一种很好的解决方案,基于事件的通知模式使得多并发时不用维持高数量的线程,高并发的socket服务器的java实现成为现实。不过原生nio代码十分复杂,无论编写还是修改都是一件头疼的事。“屏蔽底层的繁琐工作,让程序员将注意力集中于业务逻辑本身”,有需求就有生产力进步,于是各式各样的nio框架涌现而出,而笔者使用到的是其中最常见的两种:xSocket和MINA。
1 xsocket框架
官网:http://xsocket.sourceforge.net/
xSocket是一套非常简洁的nio框架,利用这套框架,你可以在完全不了解nio的情况下设计出高并发的socket服务器。
server端代码:
Java代码
public class ProjectServer extends Thread {
private static final int PORT=9099;
public void run() {
IServer srv = null;
try {
//建立handler
srv = new Server(PORT, new ProjectHandle());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//服务器运行
srv.run();
System.out.println("The ProjectServer start on port: "+PORT);
}
public static void main(String[] args) {
ProjectServer projectServer = new ProjectServer();
projectServer.start();
}
}
handler代码
Java代码
public class ProjectHandle implements IDataHandler, IConnectHandler,
IDisconnectHandler {
/* 处理连接建立事件 */
@Override
public boolean onConnect(INonBlockingConnection nbc) throws IOException,
BufferUnderflowException, MaxReadSizeExceededException {
// TODO Auto-generated method stub
System.out.println(nbc.getId() + "is connect!");
return true;
}
/* 处理连接断开事件 */
@Override
public boolean onDisconnect(INonBlockingConnection nbc) throws IOException {
// TODO Auto-generated method stub
System.out.println(nbc.getId() + "is disconnect!");
return true;
}
/* 处理接受数据事件 */
@Override
public boolean onData(INonBlockingConnection nbc) throws IOException,
BufferUnderflowException, ClosedChannelException,
MaxReadSizeExceededException {
// TODO Auto-generated method stub
String str = nbc.readStringByDelimiter("\0");
System.out.println(str);
return true;
}
}
这里我们以"\0"为间隔读取数据,xSocket还提供按照长度读取以及全部读取到一个ByteBuffer几种读取数据的方式,如果传递过程中采取byte数组格式,在接受数据时还可以使用xSocket自带的工具类DataConverter进行转化。譬如接收数据时如此操作:
Java代码
ByteBuffer copyBuffer = ByteBuffer.allocate(20000);
nbc.read(copyBuffer);
copyBuffer.flip();
String str = DataConverter.toString(copyBuffer, "utf-8");
就可以将二进制格式的传输内容还原为原始字符串了。
需要说明的是虽然xSocket代码简单、开发快捷,但是由于太“上层”了,所以很多地方不利于coder自己控制。譬如socket通信中一个很常见的“半包连包”问题用xsocket处理起来就会很麻烦,而且如果传输协议是经过特殊设计的,xsocket也无法像mina那样自己编写解码器。当然如果你不是特别计较这些方面,那么非常适于上手的xSocket就是适合你的nio框架。
另,附件中为xsocket所需要的jar包,下载后直接加载项目中即可使用。
3 MINA
项目主页:http://mina.apache.org/
闲话不说,上代码
Java代码
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();
}
}
Java代码
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将毫无作用,具体来说就是解码过滤器失效。在实际应用中,我们一般是这样的处理的:
Java代码
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端代码也要修改
Java代码
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);
}
}
注意这段
Java代码
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包,欢迎下载。
slf4j-api-1.5.3.jar (19.7 KB)
下载次数: 66
mina-core-2.0.0-M4.jar (619.8 KB)
下载次数: 81
slf4j-simple-1.5.3.jar (7.3 KB)
下载次数: 62
相关文章推荐
- nio socket 及其开源框架MINA学习总结(一)
- nio socket 及其开源框架MINA学习总结(二)
- nio socket 及其开源框架MINA学习总结(一)
- socket, nio socket 及nio socket框架MINA总结
- nio与mina学习(1) nio与socket模型的关系探究
- nio socket 及其开源框架MINA学习总结(二)
- 常见开源深度学习框架简介
- APP测试学习之造轮子--基于MINA框架的NIO
- nio socket 及其开源框架MINA学习总结
- nio socket 及其开源框架MINA学习总结(一)
- mina框架-------NioSocketAcceptor和NioSocketConnector对象
- nio socket 及其开源框架MINA学习总结(二)
- NIO通讯框架之阿堂教程:Mina学习笔记-中级进阶篇(二)
- NIO通讯框架之阿堂教程:Mina学习笔记-高级进阶篇(三)
- socket, nio socket 及nio socket框架MINA总结 (转)
- socket, nio socket 及nio socket框架MINA总结
- socket, nio socket 及nio socket框架MINA总结 (转)
- socket, nio socket 及nio socket框架MINA总结
- NIO通讯框架之阿堂教程:Mina学习笔记-入门篇(一)