Skip to content

AIO NIO异步通信框架使用指南

hely ho edited this page Jan 25, 2016 · 9 revisions

AIO/NIO异步通信框架使用指南

###一、类说明

  • 网络通信架构图

架构图


  • 网络通信集类

######AIO 网络通信类和 NIO 网络通信类均继承自这个socket连接上下文基类

类路径 说明
org.voovan.network.SocketContext socket连接上下文
  • AIO网络通信类
类路径 说明
org.voovan.network.aio.AioServerSocket Aio Socket 服务端类,继承自socket连接上下文类
org.voovan.network.aio.AioSocket Aio Socket 客户端类,继承自socket连接上下文类
org.voovan.network.aio.AioSession Aio Socket 会话类
  • NIO网络通信类
类路径 说明
org.voovan.network.nio.NioServerSocket Nio Socket 服务端类,继承socket连接上下文类
org.voovan.network.nio.NioSocket Nio Socket 客户端类,继承socket连接上下文类
org.voovan.network.nio.NioSession Nio Socket 会话类
  • 过滤器接口 #####解决消息编码和解码问题
类路径 说明
org.voovan.network.IoFilter Socket 通信过滤器类
  • 消息截断接口 #####解决 Socket 粘包的问题
类路径 说明
org.voovan.network.MessageSplitter Socket 消息截断类

###二、类方法说明 ####2.1 网络通信类使用说明 ######由于基于 AIO 和 NIO 通信的服务端类、客户端类、会话类暴露的方法都是相同,这里就只作一次说明,以下代码中*可以使用 A 和 N,分别代表 AioServerSocket 和 NioServerSocket。以下其他类似函数中*号的使用是类似的。 #####2.1.1 Socket连接上下文类 org.voovan.network.SocketContext

######在以下2.1.2和2.1.3中讲解的类均继承于这个基类

public SocketContext(String host,int port,int readTimeout)
  • 构造一个Socket服务端类。
  • host: 服务发布地址。
  • port: 服务发布端口。
  • readTimeout: 读取超时时间。
public Chain<IoFilter> filterChain()
  • 获取过滤器链。
  • 返回值: 过滤器链,可以通过这个过滤器链来管理过滤器。
public IoHandler handler()
  • 获取业务处理句柄。
  • 返回值: 业务处理句柄。
public void handler(IoHandler handler)
  • 设置消息粘包分割器。
  • handler: 消息粘包分割器。
public MessageSplitter messageSplitter()
  • 获取消息粘包分割器。
  • 返回值: 消息粘包分割器。
public void messageSplitter(MessageSplitter messageSplitter)
  • 设置业务处理句柄。
  • handler: 业务处理句柄。
public ConnectModel getConnectModel()
  • 获取连接模式。
  • 返回值: 连接模式
  • ConnectModel.SERVER: 服务模式,这个连接由 SocketServer 的 Accept 发起的连接。
  • ConnectModel.CLIENT: 客户端模式,这个连接由 SocketClient 直接发起的连接。
public String getHost()
  • 获取当前Host地址。
  • 返回值: 当前Host地址。
public int getPort()
  • 获取当前Port端口号。
  • 返回值: 当前Port端口号。
public int getReadTimeout()
  • 获取当前超时时间。
  • 返回值: 当前超时时间。

#####2.1.2 服务端类 org.voovan.network.aio.AioServerSocket

org.voovan.network.nio.NioServerSocket

public *ioServerSocket(String host,int port,int readTimeout) throws IOException
  • 构造一个Socket服务端类。
  • host: 服务发布地址。
  • port: 服务发布端口。
  • readTimeout: 读取超时时间。
public boolean isConnect() 
  • 判断当前 Socket 连接是否处于连接状态。
  • 返回值: true:处于连接状态,false:连接处于断开状态。
public boolean Close()
  • 关闭当前 Socket 连接。
  • 返回值: true:连接成功关闭,false:连接关闭失败。
public void start() throws IOException
  • 启动当前服务连接,时当前处于服务可用状态。

#####2.1.3 客户端类 org.voovan.network.aio.AioSocket

org.voovan.network.nio.NioSocket

public *ioSocket(String host, int port, int readTimeout) throws IOException 
  • 构造一个Socket客户端类。
  • host: 服务发布地址。
  • port: 服务发布端口。
  • readTimeout: 读取超时时间。
public * socketChannel()
  • 获取 SocketChannel 对象, "*"代表返回值类型。
  • 返回值: 获取当前 java 异步通信类,Aio 通信返回AsynchronousSocketChannel,Nio 通信返回SocketChannel。
public AioSession getSession()
  • 获取 Session 会话对象。
  • readTimeout: 读取超时时间。
public boolean isConnect() 
  • 判断当前 Socket 连接是否处于连接状态。
  • 返回值: true:处于连接状态,false:连接处于断开状态。
public boolean Close()
  • 关闭当前 Socket 连接。
  • 返回值: true:连接成功关闭,false:连接关闭失败。
public void start() throws Exception
  • 启动当前服务连接,时当前处于服务可用状态。

#####2.1.4 Socket会话类 org.voovan.network.aio.AioSession

org.voovan.network.nio.NioSession ######用于缓冲会话中的各种对象和会话属性。

public SocketContext sockContext()
  • 获取socket连接上下文
  • 返回值: socket连接上下文。
public boolean containAttribute(Object key)
  • 判断是否包含某个会话属性
  • ***key:***属性名称
public Object getAttribute(Object key)
  • 获取会话属性值
  • ***key:***属性名称
  • ***返回值:***属性值
public void setAttribute(Object key, Object value)
  • 设置会话属性值
  • ***key:***属性名称
  • ***value:***属性值
public void send(ByteBuffer buffer) throws IOException 
  • 发送消息
  • buffer: 发送消息的缓冲区,注意直接调用不会出发 onSent 事件。
public abstract boolean close();
  • 关闭当前 Socket 连接,不会出发 onClose 事件

#####2.1.5 过滤器接口 org.voovan.network.IoFilter ######解决消息编码和解码问题,用于再接受前或者发送后将消息发送到Socket缓冲区。

public Object decode(IoSession session,Object object)
  • 过滤器解密函数,接收事件(onRecive)前调用。
  • session: Socket 会话对象。
  • object: 缓冲区接收到的对象,如果是第一个过滤器是Bytebuffer。
public Object encode(IoSession session,Object object)
  • 过滤器加密函数,发送事件(onSend)后调用。
  • session: Socket 会话对象。
  • object: 发送到缓冲区的对象,如果是第一个过滤器是onRecive返回的对象。

#####2.1.6 消息分割判断类 org.voovan.network.MessageSplitter ######判断消息是否可分割,用于截断消息,解决消息粘包的问题(代码中包含 HTTP协议,字符串换行,定长报文的粘包实现)。

消息粘包有两种截断方式:

  • 1.消息截断器生效,则返回报文。
  • 2.消息读取时间超时,例如设置5s,则连续5秒内没有读取到有用的消息则返回报文。
public boolean canSplite(IoSession session,byte[] buffer,int elapsedtime);
  • 过滤器解密函数,接收事件(onRecive)前调用。
  • session: Socket 会话对象。
  • buffer: 缓冲区接收到的字节数组。
  • elapsedtime: 从第一次接收到现在用时(单位:millisSecond)。

###三、使用举例 ######这里使用AIO举例,NIO的例子使用类似于 AIO 的列子 #####3.1 过滤器类使用举例

package org.voovan.network.messagesplitter;

import org.voovan.network.IoSession;
import org.voovan.network.messagesplitter;

/**
 * 按换行对消息分割
 * 
 * @author helyho
 *
 */
public class LineMessageSplitter implements MessageSplitter {

	@Override
	public boolean canSplite(IoSession session, byte[] buffer, int elapsedtime) {
                //遍历每个字节,查找到换行符则返回true标识可以分割.
		for(int i=0;i<buffer.length;i++){
			if(buffer[i]=='\r' || buffer[i]=='\n'){
				return true;
			}
		}
		return false;
	}
	
}

#####3.2 业务处理句柄使用举例

package org.voovan.test.network;

import java.nio.ByteBuffer;
import org.voovan.network.IoHandler;
import org.voovan.network.IoSession;
import org.voovan.network.MessageLoader;
import org.voovan.tools.log.Logger;

/**
*客户端业务句柄类
**/
public class ClientHandlerTest implements IoHandler {

        //连接事件
	@Override
	public Object onConnect(IoSession session) {
		Logger.simple("onConnect");                      //在日志平台,输出事件名称
		session.setAttribute("key", "attribute value");  //再会话中保存属性
		String msg = new String("test message");         //组装一个消息
		return msg;                                      //返回消息,在 onConnect 事件发送消息
	}

        //连接断开事件
	@Override
	public void onDisconnect(IoSession session) {
		Logger.simple("onDisconnect");       //在日志平台,输出事件名称
	}

        //连接接收事件
	@Override
	public Object onReceive(IoSession session, Object obj) {
		Logger.simple("onRecive: "+obj.toString());  //在日志平台,输出事件名称和接受到的消息内容
		Logger.simple("Attribute onRecive: "+session.getAttribute("key")); //输出会话中保存的属性
		session.close();  //关闭 Socket 连接
		return obj;
	}

        //异常事件
	@Override
	public void onException(IoSession session, Exception e) {
		Logger.simple("onException");    //在日志平台,输出事件名称和接受到的消息内容
		e.printStackTrace();             //输入异常栈信息
	}

        //消息发送事件
	@Override
	public void onSent(IoSession session, Object obj) {
		ByteBuffer sad = (ByteBuffer)obj;     //byte缓冲区
		sad = (ByteBuffer)sad.rewind();       //byte缓冲区位置重置
		Logger.simple("onSent: "+MessageLoader.byteBufferToString(sad));  //输出事件名称和发送的消息内容
	}

}

#####3.3 服务端类使用举例

package org.voovan.test.network.aio;

import java.io.IOException;
import org.voovan.network.aio.AioServerSocket;
import org.voovan.network.filter.StringFilter;
import org.voovan.test.network.ServerHandlerTest;

public class AioServerSocketTest  {

	public static void main(String[] args) throws IOException {
		AioServerSocket serverSocket = new AioServerSocket("127.0.0.1",2031,1); //构造服务端类实例
		serverSocket.handler(new ServerHandlerTest());       //设置业务处理句柄
		serverSocket.filterChain().add(new StringFilter());  //设置消息过滤器
		serverSocket.start();                                //启动服务类
	}
}

#####3.3 客户端类使用举例

package org.voovan.test.network.aio;

import org.voovan.network.aio.AioSocket;
import org.voovan.network.filter.StringFilter;
import org.voovan.test.network.ClientHandlerTest;
import org.voovan.tools.log.Logger;

public class AioSocketTest {
	
	public static void main(String[] args) throws Exception {
		AioSocket socket = new AioSocket("127.0.0.1",2031,100); //构造客户端类实例
		socket.handler(new ClientHandlerTest());         //设置业务处理句柄
		socket.filterChain().add(new StringFilter());    //设置消息过滤器
		socket.start();                                  //启动服务类
	}
}