文档库 最新最全的文档下载
当前位置:文档库 › mina中文开发手册

mina中文开发手册

mina中文开发手册
mina中文开发手册

Apache Mina Server 2.0中文参考手册

李海峰李海峰((QQ:61673110)-Andrew830314@https://www.wendangku.net/doc/d68669307.html,

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP

协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。

Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并不适用。学习本文档,需要你已掌握JAVA IO JAVA IO、JAVA NIO JAVA NIO JAVA NIO、JAVA JAVA Socket Socket、JAVA JAVA JAVA 线程及并发库线程及并发库线程及并发库(java.util.concurrent (java.util.concurrent (java.util.concurrent.*.*.*))的知识。

Mina 同时提供了网络通信的Server 端、Client 端的封装,无论是哪端,Mina 在整个网通通信结构中都处于如下的位置:

可见Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、接收的数据以及你的业务逻辑即可。

同样的,无论是哪端,Mina 的执行流程如下所示:

(1.)

IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。

(2.)

IoProcessor:这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分IoService 与IoProcessor 两个功能接口。另外,IoProcessor 负责调用注册在IoService 上的过滤器,并在过滤器链之后调用IoHandler。

(3.)

IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的encode 与decode 是最为重要的、也是你在使用Mina 时最主要关注的地方。

(4.) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。

_______________________________________________________________________________

1. 简单的TCPServer TCPServer::

(1.) 第一步第一步::编写IoService IoService

按照上面的执行流程,我们首先需要编写IoService,IoService 本身既是服务端,又是客户端,我们这里编写服务端,所以使用IoAcceptor 实现,由于IoAcceptor 是与协议无关的,因为我们要编写TCPServer,所以我们使用IoAcceptor 的实现NioSocketAcceptor,实际上底层就是调用java.nio.channels.ServerSocketChannel 类。当然,如果你使用了Apache 的APR 库,那么你可以选择使用AprSocketAcceptor 作为TCPServer 的实现,据传说Apache APR 库的性能比JVM 自带的本地库高出很多。

那么IoProcessor 是由指定的IoService 内部创建并调用的,我们并不需要关心。

public class MyServer {

main 方法方法::

IoAcceptor acceptor=new NioSocketAcceptor();

acceptor .getSessionConfig().setReadBufferSize(2048);

acceptor .getSessionConfig.setIdleTime(IdleStatus.BOTH_IDLE,10); acceptor .bind(new InetSocketAddress(9123)); }

这段代码我们初始化了服务端的TCP/IP 的基于NIO 的套接字,然后调用IoSessionConfig 设置读取数据的缓冲区大小、读写通道均在10秒内无任何操作就进入空闲状态。

(2.) 第二步第二步::编写过滤器编写过滤器

这里我们处理最简单的字符串传输,Mina 已经为我们提供了TextLineCodecFactory 编解码器工厂来对字符串进行编解码处理。

acceptor .getFilterChain().addLast("codec",

new ProtocolCodecFilter(

new TextLineCodecFactory(

Charset.forName("UTF-8"),

LineDelimeter . WINDOWS .getValue(), LineDelimiter . WINDOWS .getValue() )

)

);

这段代码要在acceptor .bind()方法之前执行,因为绑定套接字之后就不能再做这些准备工作了。

这里先不用清楚编解码器是如何工作的,这个是后面重点说明的内容,这里你只需要清楚,我们传输的以换行符为标识的数据,所以使用了Mina 自带的换行符编解码器工厂。

(3.) 第三步第三步::编写IoHandler IoHandler

这里我们只是简单的打印Client 传说过来的数据。

public class MyIoHandler extends IoHandlerAdapter { // 这里我们使用的SLF4J 作为日志门面,至于为什么在后面说明。 private final static Logger log = LoggerFactory

.getLogger (MyIoHandler.class );

@Override

public void messageReceived(IoSession session, Object message)

throws Exception {

String str = message.toString();

log .info("The message received is [" + str + "]"); if (str.endsWith("quit")) { session.close(true ); return ;

}

}

}

然后我们把这个IoHandler 注册到IoService:

acceptor .setHandler(new MyIoHandler());

当然这段代码也要在acceptor .bind()方法之前执行。

然后我们运行MyServer 中的main 方法,你可以看到控制台一直处于阻塞状态,此时,我们用telnet 127.0.0.1 9123访问,然后输入一些内容,当按下回车键,你会发现数据在Server 端被输出,但要注意不要输入中文,因为Windows 的命令行窗口不会对传输的数据进行UTF-8编码。当输入quit 结尾的字符串时,连接被断开。

这里注意你如果使用的操作系统,或者使用的Telnet 软件的换行符是什么,如果不清楚,可以删掉第二步中的两个红色的参数,使用TextLineCodec 内部的自动识别机制。

_______________________________________________________________________________

2. 简单的TCP TCPClient Client Client::

这里我们实现Mina 中的TCPClient,因为前面说过无论是Server 端还是Client 端,在Mina 中的执行流程都是一样的。唯一不同的就是IoService 的Client 端实现是IoConnector。

(1.)第一步

并注册过滤器

:编写IoService并注册过滤器

第一步:

public class MyClient {

main方法

方法:

IoConnector connector=new NioSocketConnector();

connector.setConnectTimeoutMillis(30000);

connector.getFilterChain().addLast("codec",

new ProtocolCodecFilter(

new TextLineCodecFactory(

Charset.forName("UTF-8"),

LineDelimiter.WINDOWS.getValue(),

LineDelimiter.WINDOWS.getValue()

)

)

);

connector.connect(new InetSocketAddress("localhost", 9123));

}

IoHandler

:编写IoHandler

(2.)第三步

第三步:

public class ClientHandler extends IoHandlerAdapter {

private final static Logger LOGGER = LoggerFactory

.getLogger(ClientHandler.class);

private final String values;

public ClientHandler(String values) {

this.values = values;

}

@Override

public void sessionOpened(IoSession session) {

session.write(values);

}

}

注册IoHandler:

connector.setHandler(new ClientHandler("你好!\r\n大家好!"));

然后我们运行MyClient,你会发现MyServer输出如下语句:

The message received is [你好!]

The message received is [大家好!]

我们看到服务端是按照收到两条消息输出的,因为我们用的编解码器是以换行符判断数据是

否读取完毕的。

_______________________________________________________________________________ 3. 介绍Mina 的TCP 的主要接口的主要接口:: 通过上面的两个示例,你应该对Mina 如何编写TCP/IP 协议栈的网络通信有了一些感性的认识。

(1.)(1.)IoService IoService IoService::

这个接口是服务端IoAcceptor、客户端IoConnector 的抽象,提供IO 服务和管理IoSession 的功能,它有如下几个常用的方法:

A. TransportMetadata getTransportMetadata()TransportMetadata getTransportMetadata()::

这个方法获取传输方式的元数据描述信息,也就是底层到底基于什么的实现,譬如:nio、apr 等。

B. void addListener(IoServiceListener listener)void addListener(IoServiceListener listener)::

这个方法可以为IoService 增加一个监听器,用于监听IoService 的创建、活动、失效、空闲、销毁,具体可以参考IoServiceListener 接口中的方法,这为你参与IoService 的生命周期提供了机会。

C. void removeListener(IoServiceListener listener)void removeListener(IoServiceListener listener):: 这个方法用于移除上面的方法添加的监听器。

D. void void setHandler setHandler((IoHandler handler IoHandler handler)):

这个方法用于向IoService 注册IoHandler,同时有getHandler()方法获取Handler。

E. MapMap getManagedSessions()getManagedSessions()::

这个方法获取IoService 上管理的所有IoSession,Map 的key 是IoSession 的id。

F. IoSessionConfig getSessionConfig IoSessionConfig getSessionConfig()()()::

这个方法用于获取IoSession 的配置对象,通过IoSessionConfig 对象可以设置Socket 连接的一些选项。

_______________________________________________________________________________

(2.)(2.)IoAcceptor IoAcceptor IoAcceptor::

这个接口是TCPServer 的接口,主要增加了void bind()监听端口、void unbind()解除对套接字的监听等方法。这里与传统的JAVA 中的ServerSocket 不同的是IoAcceptor 可以多次调用bind()方法(或者在一个方法中传入多个SocketAddress 参数)同时监听多个端口。

_______________________________________________________________________________

(3.)(3.)IoConnector IoConnector IoConnector::

这个接口是TCPClient 的接口,主要增加了ConnectFuture connect(SocketAddress remoteAddress,SocketAddress localAddress)方法,用于与Server 端建立连接,第二个参数如果不传递则使用本地的一个随机端口访问Server 端。这个方法是异步执行的,同样的,也可以同时连接多个服务端。

_______________________________________________________________________________

(4.4.))IoSession IoSession::

这个接口用于表示Server 端与Client 端的连接,IoAcceptor.accept()的时候返回实例。 这个接口有如下常用的方法: A. WriteFuture write(Object WriteFuture write(Object message message)): 这个方法用于写数据,该操作是异步的。

B. CloseFuture close(boolean immediately)CloseFuture close(boolean immediately)::

这个方法用于关闭IoSession,该操作也是异步的,参数指定true 表示立即关闭,否则就在所有的写操作都flush 之后再关闭。

C. Object setAttribute(Object setAttribute(Object key,Object value)Object key,Object value)Object key,Object value)::

这个方法用于给我们向会话中添加一些属性,这样可以在会话过程中都可以使用,类似于HttpSession 的setAttrbute()方法。IoSession 内部使用同步的HashMap 存储你添加的自定义属性。

D. SocketAddress getRemoteAddress()SocketAddress getRemoteAddress():: 这个方法获取远端连接的套接字地址。

E. void suspendWrite()void suspendWrite()::

这个方法用于挂起写操作,那么有void resumeWrite()方法与之配对。对于read()方法同样适用。

F. ReadFuture read()ReadFuture read()::

这个方法用于读取数据,但默认是不能使用的,你需要调用IoSessionConfig 的setUseReadOperation(true)才可以使用这个异步读取的方法。一般我们不会用到这个方法,因为这个方法的内部实现是将数据保存到一个BlockingQueue,假如是Server 端,因为大量的Client 端发送的数据在Server 端都这么读取,那么可能会导致内存泄漏,但对于Client,可能有的时候会比较便利。

G. IoService getService IoService getService()()()::

这个方法返回与当前会话对象关联的IoService 实例。

关于TCP 连接的关闭连接的关闭::

无论在客户端还是服务端,IoSession 都用于表示底层的一个TCP 连接,那么你会发现无论

是Server 端还是Client 端的IoSession 调用close()方法之后,TCP 连接虽然显示关闭, 但主线程仍然在运行,也就是JVM 并未退出,这是因为IoSession 的close()仅仅是关闭了TCP 的连接通道,并没有关闭Server 端、Client 端的程序。你需要调用IoService 的dispose()方法停止Server 端、Client 端。

_______________________________________________________________________________

(5.)(5.)IoSessionConfig IoSessionConfig IoSessionConfig::

这个方法用于指定此次会话的配置,它有如下常用的方法: A. void setReadBufferSize(int size)void setReadBufferSize(int size)::

这个方法设置读取缓冲的字节数,但一般不需要调用这个方法,因为IoProcessor 会自动调整缓冲的大小。你可以调用setMinReadBufferSize()、setMaxReadBufferSize()方法,这样无论IoProcessor 无论如何自动调整,都会在你指定的区间。

B. void setIdleTime(IdleStatus status void setIdleTime(IdleStatus status,int idleTime ,int idleTime ,int idleTime)): 这个方法设置关联在通道上的读、写或者是读写事件在指定时间内未发生,该通道就进入空闲状态。一旦调用这个方法,则每隔idleTime 都会回调过滤器、IoHandler 中的sessionIdle()方法。

C. void setWriteTimeout(int time)void setWriteTimeout(int time):: 这个方法设置写操作的超时时间。

D. void setUseReadOperation(boolean useReadOperation void setUseReadOperation(boolean useReadOperation)): 这个方法设置IoSession 的read()方法是否可用,默认是false。

_______________________________________________________________________________

(6.)(6.)IoHandler IoHandler IoHandler::

这个接口是你编写业务逻辑的地方,从上面的示例代码可以看出,读取数据、发送数据基本都在这个接口总完成,这个实例是绑定到IoService 上的,有且只有一个实例(没有给一个IoService 注入一个IoHandler 实例会抛出异常)。它有如下几个方法:

A. void void sessionCreated sessionCreated sessionCreated(IoSession session)(IoSession session)(IoSession session):: 这个方法当一个Session 对象被创建的时候被调用。对于TCP 连接来说,连接被接受的时候调用,但要注意此时TCP 连接并未建立,此方法仅代表字面含义,也就是连接的对象IoSession 被创建完毕的时候,回调这个方法。

对于UDP 来说,当有数据包收到的时候回调这个方法,因为UDP 是无连接的。

B. void void sessionOpened sessionOpened sessionOpened((IoSession session IoSession session)):

这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP 来说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。

对于UDP 来说,这个方法与sessionCreated()没什么区别,但是紧跟其后执行。如果你每隔一段时间,发送一些数据,那么sessionCreated()方法只会在第一次调用,但是sessionOpened()方法每次都会调用。

C. void void sessionClosed sessionClosed sessionClosed((IoSession session IoSession session)) : 对于TCP 来说,连接被关闭时,调用这个方法。

对于UDP 来说,IoSession 的close()方法被调用时才会毁掉这个方法。

D. void void sessionIdle sessionIdle sessionIdle((IoSession session IoSession session,, IdleS IdleStatus status tatus status tatus status)) : 这个方法在IoSession 的通道进入空闲状态时调用,对于UDP 协议来说,这个方法始终不会被调用。

E. void void exceptionCaught exceptionCaught exceptionCaught((IoSession session, Throwable cause IoSession session, Throwable cause)) :

这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭IoSession。

F. void void messageReceived messageReceived messageReceived((IoSession session, Object message IoSession session, Object message)) :

接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message 是一个IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。通常我们都是会使用协议编解码器的,就像上面的例子,因为协议编解码器是TextLineCodecFactory,所以我们可以强制转message 为String 类型。

G. void void messageSent messageSent messageSent((IoSession session, Object message IoSession session, Object message)) :

当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,也就是说发送消息是不能用这个方法的。

发送消息的时机发送消息的时机::

发送消息应该在sessionOpened()、messageReceived()方法中调用IoSession.write()方法完成。因为在sessionOpened()方法中,TCP 连接已经真正打开,同样的在messageReceived()方法TCP 连接也是打开状态,只不过两者的时机不同。sessionOpened()方法是在TCP 连接建立之后,接收到数据之前发送;messageReceived()方法是在接收到数据之后发送,你可以完成依据收到的内容是什么样子,决定发送什么样的数据。

因为这个接口中的方法太多,因此通常使用适配器模式的IoHandlerAdapter,覆盖你所感兴趣的方法即可。

_______________________________________________________________________________

(7.)(7.)IoBuffer IoBuffer IoBuffer::

这个接口是对JAVA NIO 的ByteBuffer 的封装,这主要是因为ByteBuffer 只提供了对基本数据类型的读写操作,没有提供对字符串等对象类型的读写方法,使用起来更为方便,另外,ByteBuffer 是定长的,如果想要可变,将很麻烦。IoBuffer 的可变长度的实现类似于StringBuffer。IoBuffer 与ByteBuffer 一样,都是非线程安全的。本节的一些内容如果不清楚,可以参考java.nio.ByteBuffer 接口。 这个接口有如下常用的方法:

A. static IoBuffer allocate(static IoBuffer allocate(int capacity int capacity int capacity,boolean useDirectBuffer ,boolean useDirectBuffer ,boolean useDirectBuffer)): 这个方法内部通过SimpleBufferAllocator 创建一个实例,第一个参数指定初始化容量,第二个参数指定使用直接缓冲区还是JAVA 内存堆的缓存区,默认为false。

B. void free()void free()::

释放缓冲区,以便被一些IoBufferAllocator 的实现重用,一般没有必要调用这个方法,除非你想提升性能(但可能未必效果明显)。

C. IoBuffer IoBuffer setAutoExpand(boolean setAutoExpand(boolean autoExpand autoExpand)):

这个方法设置IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度可变这个特性默认是不开启的。

D. IoBuffer setAutoShrink(boolean autoShrink IoBuffer setAutoShrink(boolean autoShrink)):

这个方法设置IoBuffer 为自动收缩,这样在compact()方法调用之后,可以裁减掉一些没有使用的空间。如果这个方法没有被调用或者设置为false,你也可以通过调用shrink()方法手动收缩空间。

E. IoBuffer order(ByteOrder bo)IoBuffer order(ByteOrder bo)::

这个方法设置是Big Endian 还是Little Endian,JAVA 中默认是Big Endian,C++和其他语言一般是Little Endian。

F. IoBuffer asReadOnlyBuffer()IoBuffer asReadOnlyBuffer():: 这个方法设置IoBuffer 为只读的。

G. B oolean pr oolean prefixedDataAvailable(efixedDataAvailable(efixedDataAvailable(int prefixLength,int maxDataLength int prefixLength,int maxDataLength int prefixLength,int maxDataLength)):

这个方法用于数据的最开始的1、2、4个字节表示的是数据的长度的情况,prefixLentgh 表示这段数据的前几个字节(只能是1、2、4的其中一个)的代表的是这段数据的长度,maxDataLength 表示最多要读取的字节数。返回结果依赖于等式remaining()-prefixLength>=maxDataLength,也就是总的数据-表示长度的字节,剩下的字节数要比打算读取的字节数大或者相等。

H. String getPrefixedString(int prefixLength,CharsetDecoder decoder)String getPrefixedString(int prefixLength,CharsetDecoder decoder)::

如果上面的方法返回true,那么这个方法将开始读取表示长度的字节之后的数据,注意要保持这两个方法的prefixLength 的值是一样的。

G、H 两个方法在后面讲到的PrefixedStringDecoder 中的内部实现使用。

IoBuffer 剩余的方法与ByteBuffer 都是差不多的,额外增加了一些便利的操作方法,例如:IoBuffer IoBuffer putString(Strin putString(Strin putString(String value,g value,g value,Charset Charset CharsetEncoder encoder)Encoder encoder)Encoder encoder)可以方便的以指定的编码方式存储字符串、InputStream asInputStream()InputStream asInputStream()InputStream asInputStream()方法从IoBuffer 剩余的未读的数据中转为输入流等。

_______________________________________________________________________________

(8.)(8.)IoFuture IoFuture IoFuture::

在Mina 的很多操作中,你会看到返回值是XXXFuture,实际上他们都是IoFuture 的子类,看到这样的返回值,这个方法就说明是异步执行的,主要的子类有ConnectFuture、CloseFuture 、ReadFuture 、WriteFuture 。这个接口的大部分操作都和java.util.concurrent.Future 接口是类似的,譬如:await()、awaitUninterruptibly()等,一般我们常用awaitUninterruptibly()方法可以等待异步执行的结果返回。 这个接口有如下常用的方法:

A. IoFuture addListener(IoFutureListener list IoFuture addListener(IoFutureListener listener)ener)ener)::

这个方法用于添加一个监听器,在异步执行的结果返回时监听器中的回调方法operationComplete(IoFuture future),也就是说,这是替代awaitUninterruptibly()方法另一种等待异步执行结果的方法,它的好处是不会产生阻塞。

B. IoFuture removeListener(IoFuture IoFuture removeListener(IoFutureListener listener Listener listener Listener listener)): 这个方法用于移除指定的监听器。

C. IoSession getSession()IoSession getSession():: 这个方法返回当前的IoSession。

举个例子,我们在客户端调用connect()方法访问Server 端的时候,实际上这就是一个异步执行的方法,也就是调用connect()方法之后立即返回,执行下面的代码,而不管是否连接成功。那么如果我想在连接成功之后执行一些事情(譬如:获取连接成功后的IoSession 对象),该怎么办呢?按照上面的说明,你有如下两种办法: 第一种第一种::

ConnectFuture future = connector.connect(new InetSocketAddress(

HOSTNAME , PORT ));

// 等待是否连接成功,相当于是转异步执行为同步执行。 future.awaitUninterruptibly();

// 连接成功后获取会话对象。如果没有上面的等待,由于connect()方法是异步的,session 可能会无法获取。

session = future.getSession();

第二种第二种::

ConnectFuture future = connector.connect(new InetSocketAddress(

HOSTNAME , PORT ));

future.addListener(new IoFutureListener() {

@Override

public void operationComplete(ConnectFuture future) { try { Thread.sleep (5000); } catch (InterruptedException e) {

e.printStackTrace();

}

IoSession session = future.getSession();

System.out .println("++++++++++++++++++++++++++++");

}

});

System.out .println("*************");

为了更好的看清楚使用监听器是异步的,而不是像awaitUninterruptibly()那样会阻塞主线程的执行,我们在回调方法中暂停5秒钟,然后输出+++,在最后输出***。我们执行代码之后,你会发现首先输出***(这证明了监听器是异步执行的),然后IoSession 对象Created,系统暂停5秒,然后输出+++,最后IoSession 对象Opened,也就是TCP 连接建立。

_______________________________________________________________________________

4.4.日志配置日志配置日志配置::

前面的示例代码中提到了使用SLF4J 作为日志门面,这是因为Mina 内部使用的就是SLF4J,你也使用SLF4J 可以与之保持一致性。

Mina 如果想启用日志跟踪Mina 的运行细节,你可以配置LoggingFilter 过滤器,这样你可以看到Session 建立、打开、空闲等一系列细节在日志中输出,默认SJF4J 是按照DEBUG 级别输出跟踪信息的,如果你想给某一类别的Mina 运行信息输出指定日志输出级别,可以调用LoggingFilter 的setXXXLogLevel(LogLevel.XXX)。

例:

LoggingFilter lf = new LoggingFilter();

lf.setSessionOpenedLogLevel(LogLevel.ERROR); acceptor .getFilterChain().addLast("logger", lf);

这里IoSession 被打开的跟踪信息将以ERROR 级别输出到日志。

_______________________________________________________________________________

5.5.过滤器过滤器过滤器::

前面我们看到了LoggingFilter、ProtocolCodecFilter 两个过滤器,一个负责日志输出,一个负责数据的编解码,通过最前面的Mina 执行流程图,在IoProcessor 与IoHandler 之间可以有很多的过滤器,这种设计方式为你提供可插拔似的扩展功能提供了非常便利的方式,目前的Apache CXF、Apache Struts2中的拦截器也都是一样的设计思路。 Mina 中的IoFilter 是单例的,这与CXF、Apache Struts2没什么区别。 IoService 实例上会绑定一个DefaultIoFilterChainBuilder 实例,

DefaultIoFilterChainBuilder 会把使用内部的EntryImpl 类把所有的过滤器按照顺序连在一起,组成一个过滤器链。

DefaultIoFilterChainBuilder 类如下常用的方法: A. void void addFirst(addFirst(String name,IoFilter filter String name,IoFilter filter String name,IoFilter filter)): 这个方法把过滤器添加到过滤器链的头部,头部就是IoProcessor 之后的第一个过滤器。同样的addLast()方法把过滤器添加到过滤器链的尾部。

B. void addBefore(String baseName void addBefore(String baseName,,String name,IoFilter filter)String name,IoFilter filter)::

这个方法将过滤器添加到baseName 指定的过滤器的前面,同样的addAfter()方法把过滤器添加到baseName 指定的过滤器的后面。这里要注意无论是那种添加方法,每个过滤器的名字(参数name)必须是唯一的。

C. IoFilter remove(Stirng name IoFilter remove(Stirng name)):

这个方法移除指定名称的过滤器,你也可以调用另一个重载的remove()方法,指定要移除的IoFilter 的类型。

D. List> getAll()getAll()::

这个方法返回当前IoService 上注册的所有过滤器。

默认情况下,过滤器链中是空的,也就是getAll()方法返回长度为0的List,但实际Mina 内部有两个隐藏的过滤器:HeadFilter、TailFilter,分别在List 的最开始和最末端,很明显,TailFilter 在最末端是为了调用过滤器链之后,调用IoHandler。但这两个过滤器对你来说是透明的,可以忽略它们的存在。

编写一个过滤器很简单,你需要实现IoFilter 接口,如果你只关注某几个方法,可以继承IoFilterAdapter 适配器类。IoFilter 接口中主要包含两类方法,一类是与IoHandler 中的方法名一致的方法,相当于拦截IoHandler 中的方法,另一类是IoFilter 的生命周期回调方法,这些回调方法的执行顺序和解释如下所示:

(1.)init()

(1.)init()在首次添加到链中的时候被调用,但你必须将这个IoFilter 用ReferenceCountingFilter 包装起来,否则init()方法永远不会被调用。

(2.)onPreAdd()

(2.)onPreAdd()在调用添加到链中的方法时被调用,但此时还未真正的加入到链。 (3.)onPostAdd()

(3.)onPostAdd()在调用添加到链中的方法后被调,如果在这个方法中有异常抛出,则过滤器会立即被移除,同时destroy()方法也会被调用(前提是使用ReferenceCountingFilter 包装)。

(4.)onPreRemove()

(4.)onPreRemove()在从链中移除之前调用。 (5.)onPostRemove()(5.)onPostRemove()在从链中移除之后调用。 (6.)(6.)destory()destory()destory()在从链中移除时被调用,使用方法与init()要求相同。

无论是哪个方法,要注意必须在实现时调用参数nextFilter 的同名方法,否则,过滤器链的执行将被中断,IoHandler 中的同名方法一样也不会被执行,这就相当于Servlet 中的Filter 必须调用filterChain.doFilter(request,response)才能继续前进是一样的道理。

示例示例::

public class MyIoFilter implements IoFilter { @Override

public void destroy() throws Exception { System.out .println("%%%%%%%%%%%%%%%%%%%%%%%%%%%destroy");

}

@Override

public void exceptionCaught(NextFilter nextFilter, IoSession session,

Throwable cause) throws Exception {

System.out .println("%%%%%%%%%%%%%%%%%%%%%%%%%%%exceptionCaught"); nextFilter.exceptionCaught(session, cause); }

@Override

public void filterClose(NextFilter nextFilter, IoSession session)

throws Exception {

System.out .println("%%%%%%%%%%%%%%%%%%%%%%%%%%%filterClose"); nextFilter.filterClose(session);

}

@Override

public void filterWrite(NextFilter nextFilter, IoSession session,

WriteRequest writeRequest) throws Exception {

System.out .println("%%%%%%%%%%%%%%%%%%%%%%%%%%%filterWrite"); nextFilter.filterWrite(session, writeRequest); }

@Override

public void init() throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%init");

}

@Override

public void messageReceived(NextFilter nextFilter, IoSession session,

Object message) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%messageReceived");

nextFilter.messageReceived(session, message);

}

@Override

public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%messageSent");

nextFilter.messageSent(session, writeRequest);

}

@Override

public void onPostAdd(IoFilterChain parent, String name,

NextFilter nextFilter) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%onPostAdd");

}

@Override

public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%onPostRemove");

}

@Override

public void onPreAdd(IoFilterChain parent, String name,

NextFilter nextFilter) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%onPreAdd");

}

@Override

public void onPreRemove(IoFilterChain parent, String name,

NextFilter nextFilter) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%onPreRemove");

}

@Override

public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionClosed");

nextFilter.sessionClosed(session);

}

@Override

public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionCreated");

nextFilter.sessionCreated(session);

}

@Override

public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionIdle");

nextFilter.sessionIdle(session, status);

}

@Override

public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {

System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionOpened");

nextFilter.sessionOpened(session);

}

}

我们将这个拦截器注册到上面的TCPServer的IoAcceptor的过滤器链中的最后一个: acceptor.getFilterChain().addLast("myIoFilter",

new ReferenceCountingFilter(new MyIoFilter()));

这里我们将MyIoFilter用ReferenceCountingFilter包装起来,这样你可以看到init()、destroy()方法调用。我们启动客户端访问,然后关闭客户端,你会看到执行顺序如下所示:init onPreAdd onPostAdd sessionCreated sessionOpened messageReceived filt erClose sessionClosed onPreRemove onPostRemove destroy。

IoHandler的对应方法会跟在上面的对应方法之后执行,这也就是说从横向(单独的看一个过滤器中的所有方法的执行顺序)上看,每个过滤器的执行顺序是上面所示的顺序;从纵向

(方法链的调用)上看,如果有filter1、filter2两个过滤器,sessionCreated()方法的执行顺序如下所示:

filter1-sessionCreated filter2-sessionCreated IoHandler-sessionCreated。

这里你要注意init、onPreAdd、onPostAdd三个方法并不是在Server启动时调用的,而是IoSession对象创建之前调用的,也就是说IoFilterChain.addXXX()方法仅仅负责初始化过滤器并注册过滤器,但并不调用任何方法,包括init()初始化方法也是在IoProcessor开始工作的时候被调用。

IoFilter是单例的,那么init()方法是否只被执行一次呢?这个是不一定的,因为IoFilter 是被IoProcessor调用的,而每个IoService通常是关联多个IoProcessor,所以IoFilter 的init()方法是在每个IoProcessor线程上只执行一次。关于Mina的线程问题,我们后面会详细讨论,这里你只需要清楚,init()与destroy()的调用次数与IoProceesor的个数有关,假如一个IoService关联了3个IoProcessor,有五个并发的客户端请求,那么你会看到三次init()方法被调用,以后将不再会调用。

中自带的过滤器:

Mina中自带的过滤器

过滤器 说明

BlacklistFilter 设置一些IP地址为黑名单,不允许访问。 BufferedWriteFilter 设置输出时像BufferedOutputStream一样进行缓

冲。

CompressionFilter 设置在输入、输出流时启用JZlib压缩。 ConnectionThrottleFilter 这个过滤器指定同一个IP地址(不含端口号)上

的请求在多长的毫秒值内可以有一个请求,如果

小于指定的时间间隔就有连续两个请求,那么第

二个请求将被忽略(IoSession.close())。正如

Throttle的名字一样,调节访问的频率。这个过

滤器最好放在过滤器链的前面。 FileRegionWriteFilter 如果你想使用File对象进行输出,请使用这个过

滤器。要注意,你需要使用WriteFuture或者在

messageSent()方法中关闭File所关联的

FileChannel通道。

StreamWriteFilter 如果你想使用InputStream对象进行输出,请使

用这个过滤器。要注意,你需要使用WriteFuture

或者在messageSent()方法中关闭File所关联的

FileChannel通道。

NoopFilter 这个过滤器什么也不做,如果你想测试过滤器链

是否起作用,可以用它来测试。 ProfilerTimerFilter 这个过滤器用于检测每个事件方法执行的时间,

所以最好放在过滤器链的前面。

ProxyFilter 这个过滤器在客户端使用ProxyConnector作为实

现时,会自动加入到过滤器链中,用于完成代理

功能。

RequestResponseFilter 暂不知晓。

SessionAttributeInitializingFilter 这个过滤器在IoSession 中放入一些属性(Map),

通常放在过滤器的前面,用于放置一些初始化的信息。 MdcInjectionFilter 针对日志输出做MDC 操作,可以参考LOG4J 的MDC、NDC 的文档。

WriteRequestFilter

CompressionFilter、RequestResponseFilter 的基类,用于包装写请求的过滤器。

还有一些过滤器,会在各节中详细讨论,这里没有列出,譬如:前面的LoggingFilger 日志过滤器。

_______________________________________________________________________________

6.6.协议编解码器协议编解码器协议编解码器::

前面说过,协议编解码器是在使用Mina 的时候你最需要关注的对象,因为在网络传输的数据都是二进制数据(byte),而你在程序中面向的是JAVA 对象,这就需要你实现在发送数据时将JAVA 对象编码二进制数据,而接收数据时将二进制数据解码为JAVA 对象(这个可不是JAVA 对象的序列化、反序列化那么简单的事情)。

Mina 中的协议编解码器通过过滤器ProtocolCodecFilter 构造,这个过滤器的构造方法需要一个ProtocolCodecFactory,这从前面注册TextLineCodecFactory 的代码就可以看出来。 ProtocolCodecFactory 中有如下两个方法:

public interface ProtocolCodecFactory {

ProtocolEncoder getEncoder(IoSession session) throws Exception;

ProtocolDecoder getDecoder(IoSession session) throws Exception; }

因此,构建一个ProtocolCodecFactory 需要ProtocolEncoder、ProtocolDecoder 两个实例。

你可能要问JAVA 对象和二进制数据之间如何转换呢?这个要依据具体的通信协议,也就是Server 端要和Client 端约定网络传输的数据是什么样的格式,譬如:第一个字节表示数据长度,第二个字节是数据类型,后面的就是真正的数据(有可能是文字、有可能是图片等等),然后你可以依据长度从第三个字节向后读,直到读取到指定第一个字节指定长度的数据。 简单的说,HTTP 协议就是一种浏览器与Web 服务器之间约定好的通信协议,双方按照指定的协议编解码数据。我们再直观一点儿说,前面一直使用的TextLine 编解码器就是在读取网络上传递过来的数据时,只要发现哪个字节里存放的是ASCII 的10、13字符(\r、\n),就认为之前的字节就是一个字符串(默认使用UTF-8编码)。

以上所说的就是各种协议实际上就是网络七层结构中的应用层协议,它位于网络层(IP)、传输层(TCP)之上,Mina 的协议编解码器就是让你实现一套自己的应用层协议栈。

_______________________________________________________________________________ (6(6--1.)1.)简单的编解码器示例简单的编解码器示例简单的编解码器示例::

下面我们举一个模拟电信运营商短信协议的编解码器实现,假设通信协议如下所示: M sip:https://www.wendangku.net/doc/d68669307.html, SIP-C/2.0 S: 1580101xxxx R: 1889020xxxx

L: 21

Hello World!

这里的第一行表示状态行,一般表示协议的名字、版本号等,第二行表示短信的发送号码,第三行表示短信接收的号码,第四行表示短信的字节数,最后的内容就是短信的内容。 上面的每一行的末尾使用ASC II 的10(\n )作为换行符,因为这是纯文本数据,协议要求双方使用UTF-8对字符串编解码。

实际上如果你熟悉HTTP 协议,上面的这个精简的短信协议和HTTP 协议的组成是非常像的,第一行是状态行,中间的是消息报头,最后面的是消息正文。

在解析这个短信协议之前,你需要知晓TCP 的一个事项,那就是数据的发送没有规模性,所谓的规模性就是作为数据的接收端,不知道到底什么时候数据算是读取完毕,所以应用层协议在制定的时候,必须指定数据读取的截至点。一般来说,有如下三种方式设置数据读取的长度:

(1.)使用分隔符,譬如:TextLine 编解码器。你可以使用\r 、\n 、NUL 这些ASC II 中的特殊的字符来告诉数据接收端,你只要遇见分隔符,就表示数据读完了,不用在那里傻等着不知道还有没有数据没读完啊?我可不可以开始把已经读取到的字节解码为指定的数据类型了啊?

(2.)定长的字节数,这种方式是使用长度固定的数据发送,一般适用于指令发送,譬如:数据发送端规定发送的数据都是双字节,AA 表示启动、BB 表示关闭等等。

(3.)在数据中的某个位置使用一个长度域,表示数据的长度,这种处理方式最为灵活,上面的短信协议中的那个L 就是短信文字的字节数,其实HTTP 协议的消息报头中的Content-Length 也是表示消息正文的长度,这样数据的接收端就知道我到底读到多长的字节数就表示不用再读取数据了。

相比较解码(字节转为JAVA 对象,也叫做拆包)来说,编码(JAVA 对象转为字节,也叫做打包)就很简单了,你只需要把JAVA 对象转为指定格式的字节流,write()就可以了。

下面我们开始对上面的短信协议进行编解码处理。 第一步第一步,,协议协议对象对象对象::

public class SmsObject { private String sender ;// 短信发送者 private String receiver ;// 短信接受者 private String message ;// 短信内容 public String getSender() { return sender ;

}

public void setSender(String sender) {

this .sender = sender;

}

public String getReceiver() {

return receiver;

}

public void setReceiver(String receiver) {

this.receiver = receiver;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

编码器:

第二步,编码器

在Mina中编写编码器可以实现ProtocolEncoder,其中有encode()、dispose()两个方法需要实现。这里的dispose()方法用于在销毁编码器时释放关联的资源,由于这个方法一般我们并不关心,所以通常我们直接继承适配器ProtocolEncoderAdapter。

public class CmccSipcEncoder extends ProtocolEncoderAdapter { private final Charset charset;

public CmccSipcEncoder(Charset charset) {

this.charset = charset;

}

@Override

public void encode(IoSession session, Object message,

ProtocolEncoderOutput out) throws Exception {

SmsObject sms = (SmsObject) message;

CharsetEncoder ce = charset.newEncoder();

IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);

String statusLine = "M sip:https://www.wendangku.net/doc/d68669307.html, SIP-C/2.0";

String sender = sms.getSender();

String receiver = sms.getReceiver();

String smsContent = sms.getMessage();

buffer.putString(statusLine + '\n', ce);

buffer.putString("S: " + sender + '\n', ce);

buffer.putString("R: " + receiver + '\n', ce); buffer .putString("L: " + (smsContent.getBytes(charset).length) + "\n",

ce);

buffer.putString(smsContent, ce); buffer.flip(); out.write(buffer);

}

}

这里我们依据传入的字符集类型对message 对象进行编码,编码的方式就是按照短信协议拼装字符串到IoBuffer 缓冲区,然后调用ProtocolEncoderOutput 的write()方法输出字节流。这里要注意生成短信内容长度时的红色代码,我们使用String 类与Byte[]类型之间的转换方法获得转为字节流后的字节数。 解码器的编写有以下几个步骤:

A. 将encode()方法中的message 对象强制转换为指定的对象类型;

B. 创建IoBuffer 缓冲区对象,并设置为自动扩展;

C. 将转换后的message 对象中的各个部分按照指定的应用层协议进行组装,并put()到

IoBuffer 缓冲区;

D. 当你组装数据完毕之后,调用flip()方法,为输出做好准备,切记在write()方法之前,

要调用IoBuffer 的flip()方法,否则缓冲区的position 的后面是没有数据可以用来输出的,你必须调用flip()方法将position 移至0,limit 移至刚才的position。这个flip()方法的含义请参看java.nio.ByteBuffer。

E. 最后调用ProtocolEncoderOutput 的write()方法输出IoBuffer 缓冲区实例。

第三步,解码器解码器::

在Mina 中编写解码器,可以实现ProtocolDecoder 接口,其中有decode()、finishDecode()、dispose()三个方法。这里的finishDecode()方法可以用于处理在IoSession 关闭时剩余的未读取数据,一般这个方法并不会被使用到,除非协议中未定义任何标识数据什么时候截止的约定,譬如:Http 响应的Content-Length 未设定,那么在你认为读取完数据后,关闭TCP 连接(IoSession 的关闭)后,就可以调用这个方法处理剩余的数据,当然你也可以忽略调剩余的数据。同样的,一般情况下,我们只需要继承适配器ProtocolDecoderAdapter,关注decode()方法即可。

但前面说过解码器相对编码器来说,最麻烦的是数据发送过来的规模,以聊天室为例,一个TCP 连接建立之后,那么隔一段时间就会有聊天内容发送过来,也就是decode()方法会被往复调用,这样处理起来就会非常麻烦。那么Mina 中幸好提供了CumulativeProtocolDecoder 类,从名字上可以看出累积性的协议解码器,也就是说只要有数据发送过来,这个类就会去读取数据,然后累积到内部的IoBuffer 缓冲区,但是具体的拆包(把累积到缓冲区的数据解码为JAVA 对象)交由子类的doDecode()方法完成,实际上CumulativeProtocolDecoder 就是在decode()反复的调用暴漏给子类实现的doDecode()方法。 具体执行过程如下所示:

A. 你的doDecode()方法返回true 时,CumulativeProtocolDecoder 的decode()方法会首

先判断你是否在doDecode()方法中从内部的IoBuffer 缓冲区读取了数据,如果没有,

则会抛出非法的状态异常,也就是你的doDecode()方法返回true就表示你已经消费了本次数据(相当于聊天室中一个完整的消息已经读取完毕),进一步说,也就是此时你必须已经消费过内部的IoBuffer缓冲区的数据(哪怕是消费了一个字节的数据)。如果验证过通过,那么CumulativeProtocolDecoder会检查缓冲区内是否还有数据未读取,如果有就继续调用doDecode()方法,没有就停止对doDecode()方法的调用,直到有新的数据被缓冲。

B.当你的doDecode()方法返回false时,CumulativeProtocolDecoder会停止对doDecode()

方法的调用,但此时如果本次数据还有未读取完的,就将含有剩余数据的IoBuffer缓冲区保存到IoSession中,以便下一次数据到来时可以从IoSession中提取合并。如果发现本次数据全都读取完毕,则清空IoBuffer缓冲区。

简而言之,当你认为读取到的数据已经够解码了,那么就返回true,否则就返回false。这个CumulativeProtocolDecoder其实最重要的工作就是帮你完成了数据的累积,因为这个工作是很烦琐的。

public class CmccSipcDecoder extends CumulativeProtocolDecoder { private final Charset charset;

public CmccSipcDecoder(Charset charset) {

this.charset = charset;

}

@Override

protected boolean doDecode(IoSession session, IoBuffer in,

ProtocolDecoderOutput out) throws Exception {

IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);

CharsetDecoder cd = charset.newDecoder();

int matchCount = 0;

String statusLine = "", sender = "", receiver = "", length = "",

sms = "";

int i = 1;

while (in.hasRemaining()) {

byte b = in.get();

buffer.put(b);

if (b == 10 && i < 5) {

matchCount++;

if (i == 1) {

buffer.flip();

statusLine = buffer.getString(matchCount, cd);

statusLine = statusLine.substring(0,

statusLine.length() - 1);

matchCount = 0;

buffer.clear();

}

Java程序员必须了解的20个lib库

Java程序员必须了解的20个lib库 一般一个经验丰富的开发者,一般都喜欢使用开源的第三方api库来进行开发,毕竟这样能够提高开发效率,并且能够简单快速的集成到项目中去,而不用花更多的时间去在重复造一些无用的轮子,多了解一些第三方库可以提高我们的开发效率,下面就来看一下在开发过程中经常会用到的一些开发第三方库,也可能不是太全,就列举一些常见或者常用的吧。 1,日志库 日志库是最常用的,毕竟在开发项目的过程中都需要使用日志来记录项目的运行信息,从而很快的定位项目的发生的问题。尽管JDK附带了自己的日志库,但是还有更好的选择,例如Log4j、SLF4j和LogBack。一般建议使用SLF4j。比如Alibaba开发手册上也是这样说的,毕竟SLF4J使您的代码独立于任何特定的日志API,就是在项目的其它框架中使用了其它的日志框架库也能够很好的集成。 2,JSON转换库 在当今的web服务、手机api接口开发和物联网世界中,JSON已经成为将信息从客户端传送到服务器的首选协议。它们前端要学好必须每天坚持学习。为了方便大家的交流学习,也是创建了一个群每天都有分享学习方法和专业老师直播

前端课程,这个扣裙首先是132 中间是667 最后是127 前端学习零基础想要学习的同学欢迎加入,如果只是凑热闹就不要来了!!!已经取代了XML,成为以独立于平台的方式传输信息的首选方式。不幸的是,JDK没有JSON库。但是,有许多优秀的第三方库允许您解析和创建JSON消息,比如Jackson和Gson,FastJson。 3,单元测试库库 单元测试是区分普通开发人员和优秀开发人员的最重要的东西。程序员经常被给予不写单元测试的借口,但是最常见的避免单元测试的借口是缺乏流行的单元测试库的经验和知识,包括JUnit、Mockito和PowerMock。 4,通用类库 Java开发人员可以使用一些优秀的通用第三方库,比如Apache Commons和谷歌Guava。我总是在我的项目中包含这些库,因为它们简化了许多任务。正如约书亚?布洛赫(Joshua Bloch)在《Effective Java》一书中正确指出的那样,重新发明轮子是没有意义的。我们应该使用经过测试的库,而不是时不时地编写我们自己的程序。对于开发人员来说,熟悉Apache Commons和谷歌Guava 是很有用的。 5,HTTP库

世界港口中英文及缩写对照

世界港口中英文及缩写对照 Aarhus 45 丹麦DKAAR 阿路斯 Abidjan 225 科特迪瓦CIABJ 阿必尚 Abu Dhabi 971 阿拉伯联合大公国AEAUH 阿布答比Acajutla 503 萨尔瓦多SVAQJ 阿卡加地 Acapulco 52 墨西哥MXACA 阿加普可 Adelaide 61 澳洲AUADL 阿得雷德 Aden 967 也门YEADE 亚丁 Alexandria 20 埃及EGALY 亚历山大 Algiers 213 阿尔及利亚DZALG 阿尔及耳 Alicante 34 西班牙ESALC 亚利坎培 Amsterdam 31 荷兰NLAMS 阿姆斯特丹 An Ping 886 台湾TWANP 安平港 Ancona 39 意大利ITAOI 安科那 Antofagasta 56 智利CLANF 安多法加斯大Antwerp 32 比利时BEANR 安特卫普 Apapa 奈及利亚NGAPP Apia 萨摩亚WSAPW 阿比亚 Aqaba 962 约旦JOAQJ 阿卡巴 Arica 56 智利CLARI 阿立卡 Aruba Is. 297 荷属安地列斯ANAUA 阿鲁巴Ashdod 972 以色列ILASH 亚实突 Assab 251 依索比亚ETASA 阿沙布 Asuncion 595 巴拉圭PYASU 亚松森 Athens 30 希腊GRATH 雅典 Atlanta 1 美国USATL 亚特兰大 Auckland 64 纽西兰NZAKL 奥克兰 Bahrain 973 巴林BHBAH 巴林 Balbo 507 巴拿马PABLB 巴波亚 Baltimore 1 美国USBAL 巴的摩尔 Bandar abbas 98 伊朗IRBND 阿巴市 Bangkok 66 泰国THBKK 曼谷 Banjul 220 甘比亚GMBJL 班久尔 Barcelona 34 西班牙ESBCN 巴塞罗那Barranquilla 57 哥伦比亚COBAQ 巴兰圭拉 Basle (basel) 41 瑞士CHBSL 巴萨尔 Basuo 86 中国大陆CNBSP 八所港 Beihai 86 中国大陆CNBEH 北海 Beira 莫桑比克MZBEW 贝伊拉 Beiruit 961 黎巴嫩LBBEY 贝鲁特 Belawan 62 印度尼西亚IDBLW 棉兰 Belfast 44 英国GBBEL 伯尔发斯特

史上最全Java基础知识点归纳

史上最全Java基础知识点归纳 写这篇文章的目的是想总结一下自己这么多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,所以也希望能分享给刚刚入门的Java 程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能让大家更好学习和使用Java。 这次介绍的主要内容是和J2SE相关的部分,另外,会在以后再介绍些J2EE 相关的、和Java中各个框架相关的内容。 经过这么多年的Java开发,以及结合平时面试Java开发者的一些经验,我觉得对于J2SE方面主要就是要掌握以下的一些内容。 1.JVM相关(包括了各个版本的特性) 对于刚刚接触Java的人来说,JVM相关的知识不一定需要理解很深,对此里面的概念有一些简单的了解即可。不过对于一个有着3年以上Java经验的资

深开发者来说,不会JVM几乎是不可接受的。 JVM作为Java运行的基础,很难相信对于JVM一点都不了解的人可以把Java语言吃得很透。我在面试有超过3年Java经验的开发者的时候,JVM几乎就是一个必问的问题了。当然JVM不是唯一决定技术能力好坏的面试问题,但是可以佐证Java开发能力的高低。 在JVM这个大类中,我认为需要掌握的知识有: JVM内存模型和结构 GC原理,性能调优 调优:Thread Dump,分析内存结构 class二进制字节码结构,class loader体系,class加载过程,实例创建过程 方法执行过程 Java各个大版本更新提供的新特性(需要简单了解) 2.Java的运行(基础必备) 这条可能出看很简单,Java程序的运行谁不会呢?不过很多时候,我们只是单纯通过IDE去执行Java程序,底层IDE又是如何执行Java程序呢?很多人并不了解。

《台大中文学报》撰稿格式

《臺大中文學報》撰稿格式 壹、中文部分 一、各章節使用符號,依一(一),1(1)……等順序表示。 二、請用新式標點,惟書名號用《》,篇名號用〈〉,書名和篇名連用時,省略篇名號, 如《莊子?天下篇》。 三、獨立引文,每行低三格。 四、注釋號碼請用阿拉伯數字標示,如①②③……。 五、文後不另列引用書目或參考書目為原則。 注釋之體例,請依下列格式撰寫: (一)引用專書: 王夢鷗:《禮記校證》(臺北:藝文印書館,1976年12月),頁102。 (二)引用論文: 1.期刊論文: 徐信義:〈張炎的詞學批評〉,《幼獅學誌》第14期(1977年2月),頁172-194。 2.論文集論文: 余英時:〈清代思想史的一個新解釋〉,《歷史與思想》(臺北:聯經出版事業公司,1976年9月),頁121-156。 3.學位論文: 孔仲溫:《類篇研究》(臺北:政治大學中國文學研究所博士論文,ooo先生指導,1985年),頁466。 (三)引用古籍: 1.古籍原刻本: 宋?司馬光:《資治通鑑》(南宋鄂州覆北宋刊龍爪本,約西元12世紀),卷2,頁 2上。 2.古籍影印本: 明?郝敬:《尚書辨解》(臺北:藝文印書館,1969年,百部叢書集成影印湖北叢書 本),卷3,頁2上。 (四)引用報紙: 丁邦新:〈國內漢學研究的方向和問題〉,《中央日報》第22版(1988年4月2日)。 (五)再次徵引: 1.再次徵引時可用簡單方式處理,如:

①王叔岷:〈論校詩之難〉,《臺大中文學報》第3期(1989年12月),頁1。 ②同前註。 ③同前註,頁3。 2.如果再次徵引的註,不接續,可用下列方式表示: ④同註①,頁5。 貳、外文部分 一、引用專書: Edwin O. James, Prehistoric Religion: A Study in Prehistoric Archaeology(史前宗教:史 前考古學的研究) (London: Thames and Hudson, 1957), p.18. 二、引用論文: 1.期刊 Richard Rudolph, “The Minatory Crossbowman in Early Chinese Tombs,”(中國早期墓葬的強弩使用者) Archives of the Chinese Art Society of America, 19(1965),pp.8-15. 2.論文集 E.G. Pulleyblank, “The Chinese and their Neighbors in Prehistoric and Early Historic Times,”(史前與早期歷史的中國人與其四鄰)in David N. Keightley,ed., The Origins of Chinese Civilization (Berkeley:University of California Press,1983),pp.460-463. 3.學位論文 Edwin O. James, Prehistoric Religion:A Study in Prehistoric Archaeology (史前宗教:史前考古學的研究) (Cambridge:Harvard University Ph. D. dissertation ,○○○先生指導,1957年),p.18. 4.學術討論會 Edward L.Shanghnessy, “Historical Perspectives on the In troduction of Chariot into China,”(車子傳入中國的歷史回顧)paper presented to the ?th Conference of the American Historical Association, New York, 1985. 1.見郭沫若:《十批判書》,《民國叢書》(上海:上海書局,1992年12月,重印民國36年上 海群益書局版),4-1冊(41冊?),頁164-166,170-171。 2.見宋?楊時:《龜山集語錄一》(臺北:商務印書館,出版年不詳,四庫全書珍本?集)第992 冊,卷10,頁3上。

Mina2源码分析

Mina2.0框架源码剖析(一) 整个框架最核心的几个包是:org.apache.mina.core.service, org.apache.mina.core.session, org.apache.mina.core.polling以及 org.apache.mina.transport.socket。 这一篇先来看org.apache.mina.core.service。第一个要说的接口是IoService,它是所有IoAcceptor和IoConnector的基接口.对于一个IoService,有哪些信息需要我们关注呢?1)底层的元数据信息TransportMetadata,比如底层的网络服务提供者(NIO,ARP,RXTX等),2)通过这个服务创建一个新会话时,新会话的默认配置IoSessionConfig。3)此服务所管理的所有会话。4)与这个服务相关所产生的事件所对应的监听者(IoServiceListener)。5)处理这个服务所管理的所有连接的处理器(IoHandler)。6)每个会话都有一个过滤器链(IoFilterChain),每个过滤器链通过其对应的IoFilterChainBuilder来负责构建。7)由于此服务管理了一系列会话,因此可以通过广播的方式向所有会话发送消息,返回结果是一个WriteFuture集,后者是一种表示未来预期结果的数据结构。8)服务创建的会话(IoSession)相关的数据通过IoSessionDataStructureFactory来提供。9)发送消息时有一个写缓冲队列。10)服务的闲置状态有三种:读端空闲,写端空闲,双端空闲。11)还提供服务的一些统计信息,比如时间,数据量等。 IoService这个服务是对于服务器端的接受连接和客户端发起连接这两种行为的抽象。 再来从服务器看起,IoAcceptor是IoService 的子接口,它用于绑定到指定的ip和端口,从而接收来自客户端的连接请求,同时会fire相应的客户端连接成功接收/取消/失败等事件给自己的IoHandle去处理。当服务器端的Accpetor从早先绑定的ip和端口上取消绑定时,默认是所有的客户端会话会被关闭,这种情况一般出现在服务器挂掉了,则客户端收到连接关闭的提示。这个接口最重要的两个方法是bind()和unbind(),当这两个方法被调用时,服务端的连接接受线程就启动或关闭了。 再来看一看客户端的连接发起者接口IoConnector,它的功能和IoAcceptor基本对应的,它用于尝试连接到服务器指定的ip和端口,同时会fire相应的客户端连接事件给自己的IoHandle去处理。当connet方法被调用后用于连接服务器端的线程就启动了,而当所有的连接尝试都结束时线程就停止。尝试连接的超时时间可以自行设置。Connect方法返回的结果是ConnectFuture,这和前面说的WriteFuture类似,在后面会有一篇专门讲这个模式的应用。 前面的IoAcceptor和IoConnector就好比是两个负责握手的仆人,而真正代表会话的实际I/O操作的接口是IoProcessor,它对现有的Reactor模式架构的Java NIO框架继续做了一层封装。它的泛型参数指明了它能处理的会话类型。接口中最重要的几个方法,add用于将指定会话加入到此Processor中,让它负责处理与此会话相关的所有I/O操作。由于写操作会有一个写请求队列,flush就用于对指定会话的写请求队列进行强制刷数据。remove方法用于从此Processor中移除和关闭指定会话,

JAVA NIO基础知识总结二_2012-1-9

JA V A NIO基础知识总结二 (一)、回顾一下总结一: (1)、NIO的几个概念: ①、Buffer :内存块,实质就是一个数组。NIO数据读或写得中转地。 ②、Channel:连接设备的通道。用于向buffer提供数据或者读取数据,异步I/O支持。 ③、Selector :channel事件的监听者,他能检测到一个或多个通道,并将事件分发出去 ④、SelectionKey:channel上发生的事件,包含了事件的状态信息和时间以及对应的channel。 (2)、在前面总结一中,最后的时候给出了一个完整的关于NIO操作网络套接字的例子,在这里先总结一下构建基于NIO的服务端的一般步骤:①、构造一个Selector ②、打开一个serverSocketChannel ③、设定serverSocketChannel为非阻塞 ④、绑定socketserverChannel到一个主机地址和端口 ⑤、注册selector并告知感兴趣的事情 (3)、Channel的状态有四种: ①、Connectable:当一个Channel完成socket连接操作已完成或者已失败。

②、Acceptable:当一个Channel已准备好接受一个新的socket连接时,channel是Acceptale ③、Readable:当一个channel能被读时。 ④、Writable:当一个Channel能被写时为可写状态。 (4)、下面是NIO中的关系图,来自于《java编程思想》

(二)、基于多线程的NIO 总结一的例子,是基于单线程的,单线程的好处是简单,不用去考虑过于复杂的线程问题,但是仔细想一下,如果数据在网络传输的过程中发生了阻塞呢,那岂不是要花费很多的时间?再者如果我们要实现像QQ中的聊天室呢,如何实现呢?。为了解决这些问题,我们现在试着采用多线程的,但是采用多线程,会产生很多线程,创建、销毁线程都是要花费时间的,所以这里可以运用到线程池来管理。 下面一个例子是:客户端发来信息,服务端然后转发所有的信息给在线的客户端。import java.io.IOException; import https://www.wendangku.net/doc/d68669307.html,.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; public class RSocketServer implements Runnable { private final static int POOLSIZE = 100;// 处理线程池的大小 private SelectionKey selectionKey; // 选择键 private ExecutorService service = Executors.newFixedThreadPool(POOLSIZE);// 固定大小的线程池 private boolean isRunning = true; private Selector selector;// 选择器 private String writeMsg;// 需要写的信息 private ServerSocketChannel ssc; public RSocketServer() { try { selector = Selector.open(); ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.socket().bind(new InetSocketAddress(8080)); selectionKey = ssc.register(selector, SelectionKey.OP_ACCEPT); System.out.println("服务器启动成功!正在端口为8080上等待..."); } catch (Exception e) { e.printStackTrace(); } } public void run() { try {

mina 框架学习

mina 框架学习 转帖:https://www.wendangku.net/doc/d68669307.html,/s/blog_5f9beca40101ee6w.html 1、简介 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP 协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。Apache Mina也称为: l NIO框架 l客户端/服务端框架(典型的C/S架构) l 网络套接字(networking socket)类库 2、通信流程 那么让我们来看一下mina在我们应用中处于什么样的一个位置呢 上图可以看出mina位于应用程序和底层网络传输之间,它不关心底层网络数据如何传输,只负责接收底层数据,过滤并转换为Java对象提供给我们的应用程序,然后把应用程序响应值过滤并转换为底层识别的字节,提供给底层传输。 再来看一下mina 通信流程图

可以很清晰看出mina主要有三个主要的业务接口:IoService,IoFilter和IoHandler (1) IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。 (2) IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的encode 与decode 是最为重要的、也是你在使用Mina 时最主要关注的地方。 (3) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。 总的来说创建一个基于mina框架的应用分为三个模块: 创建连接(IoService))——>添加消息过滤器(IoFilter)——>添加业务处理(IoHandler) 3、server 和client mina中server和client没有多大区别都是通过Ioservice建立连接和通信的,来看下具体流程 Server 一般地,服务端会有一个端口来监听client的请求/packet,并且为每隔connect建立一个session(无论是基于TCP/IP协议还是UDP协议),Server端主要通过IoAccptor建立连接

MINA网络通信框架

MINA网络通信框架 Posted by kunshuo on 2012-04-11Leave a comment (1)Go to comments MINA网络通信框架 基本介绍: Apache MINA 2是一个开发高性能和高可伸缩性网络应用程序的网络应用框架。它提供了一个抽象的事件驱动的异步API,可以使用TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式。Apache MINA 2可以作为开发网络应用程序的一个良好基础。 Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、 接收的数据以及你的业务逻辑即可。 mina的基本架构: 在图中的模块链中,IoService 便是应用程序的入口,相当于我们前面代码中的IoAccepter,IoAccepter 便是IoService 的一个扩展接口。

IoService 接口可以用来添加多个IoFilter,这些IoFilter 符合责任链模式并由IoProcessor 线程负责调用。而IoAccepter 在ioService 接口的基础上还提供绑定某个通讯端口以及取消绑定的接口。ioHandler则为应用逻辑处理类。 主要类以及接口: (1.)IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监 听是否有连接被建立。 (2.)IoProcessor:这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是 说它也拥有自己的Selector,这是与我们使用JAVA NIO编码时的一个不同之处, 通常在JAVA NIO编码中,我们都是使用一个Selector,也就是不区分IoService 与IoProcessor两个功能接口。另外,IoProcessor负责调用注册在IoService上 的过滤器,并在过滤器链之后调用IoHandler。 (3.)IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、 数据的编码(write方向)与解码(read方向)等功能,其中数据的encode 与decode 是最为重要的、也是你在使用Mina时最主要关注的地方。

网络编程框架

网络编程框架 Socket编程接口 NIO编程接口 Leader Follower 原理SEDA原理 Netty编程框架 Mina编程框架 Web编程框架 分布式应用 ?负载均衡器/Load Balancer Session Stickiness ?内存状态复制/Replication Sysch-replication Asych-replication ?Local Cache

ConcurrentHashMap FastMap Local Queue Queues Queues类似于沟通“生产者”和“消费者”的管道。组件从管道的一端放入,然后从另一端取出:“先进先出”(FIFO)的顺序。Queue接口在JavaSE5新添加到java.util中的,能够被用于单线程访问的场景中,主要适用于多个生产者、一个或多个消费者的情景,所有的读写操作都是基于同一个队列。 java.util.concurrent包中的BlockingQueue接口是Queue的子接口,而且还添加了新的特性处理如下场景:队列满(此时刚好有一个生产者要加入一个新的组件)、队列空(此时刚好有一个消费者读取或者删除一个组件)。BlockingQueue提供如下方案解决这些情况:一直阻塞等待直到其他线程修改队列的数据状态;阻塞一段时间之后返回,如果在这段时间内有其他线程修改队列数据,那么也会返回。

Deque 在JavaSE6中新增加了两端都可以添加和删除的队列-Deque (发音 "deck",not "dick"). Deques不仅可以从一端添加元素,从另一端移除,而且两端都可以添加和删除元素。如同BlockingQueue,BlockingDeque接口也为阻塞等待和超时等待的特殊情况提供了解决方法。因为Deque继承Queue、BlockingDeque继 Deque的一个特殊应用场景是只在一个端口进行添加、删除、检查操作--堆栈(first-in-last-out顺序)。Deque接口提供了stack相同的方法:push(), pop()和peek(),这方法和addFirst(), removeFirst(), peekFirst()一一对应,可以把Deque的任何一个实现类当做堆栈使用。表6中是JDK中Deque和BlockingDeque的实现。注意Deque继承Queue,BlockingDeque继承自BlockingQueue。 分布式缓存 Coherence Jboss Cache Mem Cache 分布式数据存储 数据库的垂直划分和水平划分

关于Apache Mina

关于Apache Mina 一、介绍 MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架。通过使用MINA框架可以可以省下处理底层I/O和线程并发等复杂工作,开发人员能够把更多的精力投入到业务设计和开发当中。MINA框架的应用比较广泛,应用的开源项目有Apache Directory、AsyncWeb、Apache Qpid、QuickFIX/J、Openfire、SubEthaSTMP、red5等。 MINA框架的特点有:基于java NIO类库开发;采用非阻塞方式的异步传输;事件驱动;支持批量数据传输;支持TCP、UDP协议;控制反转的设计模式(支持Spring);采用优雅的松耦合架构;可灵活的加载过滤器机制;单元测试更容易实现;可自定义线程的数量,以提高运行于多处理器上的性能;采用回调的方式完成调用,线程的使用更容易。 二、调用过程 在图中的模块链中,IoService 便是应用程序的入口,相当于代码中的 IoAccepter,IoAccepter 便是 IoService 的一个扩展接口。IoService 接口可以用来添加多个 IoFilter,这些 IoFilter 符合责任链模式并由 IoProcessor 线程负责调用。而 IoAccepter 在 ioService 接口的基础上还提供绑定某个通讯端口以及取消绑定的接口。 在上图中最右端也就是 IoHandler,这便是业务处理模块。在业务处理类中不需要去关心实际的通讯细节,只管处理客户端传输过来的信息即可。编写 Handler 类就是使用 MINA 开发网络应用程序的重心所在,相当于 MINA 已经帮你处理了所有的通讯方面的细节问题。为了简化 Handler 类,MINA 提供了 IoHandlerAdapter 类,此类仅仅是实现了 IoHandler 接口,但并不做任何处理。 IoHandler 接口中具有如下一些方法: Java代码 1.public interface IoHandler { 2. void sessionCreated(IoSession session) throws Exception;//会话创建 3. void sessionOpened(IoSession session) throws Exception;//打开会话,与 sessionCreated最大的区别是它是从另一个线程处调用的 4. void sessionClosed(IoSession session) throws Exception;//会话结束,当连接 关闭时被调用 5. void sessionIdle (IoSession session, IdleStatus status) throws Except ion;//会话空闲 6. void exceptionCaught(IoSession session, Throwable cause) throws Exceptio n;//异常捕获,Mina会自动关闭此连接

杂志广告推广方案

2011“迪亚兹”静脉曲张袜—《米娜时尚国际中文版》杂志 广告推广方案 一、产品背景介绍 1、产品名称 迪亚兹瘦腿袜 2、产生背景 塑形美腿袜因安全、可靠、有效,依靠口碑传播得以在爱美女性间广泛宣传。而蔡依林和小S在电视节目中,对静脉曲张袜产品的赞许也更加加大了产品的普及。 3、产品简介 迪亚兹瘦腿袜,主要是靠特殊压强部位的“压力”来达到首推的效果,所以对多肌肉型MM 来说,效果会减弱,但瘦腿袜可以很好的缓解肌肉酸痛、浮肿等症状,所以对于保健功效肌肉和肥肉型MM都是一样的,对于肥胖型的MM几乎是穿上即可看到效果,真正的瘦腿的时候看个人情况而定。 4、产品类型 连裤袜、九分裤、袜子、丝袜、睡眠袜 5、目标消费者 1、长时间站立(收银员、教室、医生、护士、交警、服务员) 2、长时间静坐(IT人士、白领) 3、经常出差,坐飞机(空姐、乘务员) 二、媒介选择分析 《米娜时尚国际中文版》杂志系由日本著名出版业者主妇之友出版社独家授权在中国大陆地区发行的全新形态女性休闲时尚杂志,也是一本“专注于自己的流行”的时尚杂志。她致力于推荐从日本原宿街头兴起的“混搭”休闲服饰风格,这股潮流风格,不仅影响了近几年的日本、也给台湾和香港的年轻人诠释了一种全新的时尚概念。 1、创刊影响 《米娜时尚国际中文版》杂志系由日本著名出版业者主妇之友出版社独家授权在中国大陆地区发行的全新形态女性休闲时尚杂志,也是一本“专注于自己的流行”的时尚杂志。她致力于推荐从日本原宿街头兴起的“混搭”休闲服饰风格,这股潮流风格,不仅影响了近几年的日本、也给台湾和香港的年轻人诠释了一种全新的时尚概念。今天,她的面世,也将为中国的时尚青年带来一股清新之风。米娜就像这样一个女孩:年轻不造作,柔美不浓艳;时尚但很个性;时髦却不盲从;注重细节;充满梦想,热爱都市生活,是因为可爱而美丽的人气女性。“米娜时尚”的出现为混搭风提供了很好的诠释平台,在充斥着针对都市白领女性上班着装指导的女性杂志市场上,米娜时尚国际中文版的出现对于中国都市女性来说,不只是在欧美时尚杂志之外多了一种选择而已,而是更能贴近亚洲女性对Fashion的实际需求。传统的时髦的形象仅仅取决于如何“穿”,但是“混搭”的概念将让流行变得更为个性与自信,她的诀窍就是由简单的单品作为时髦的元素,用最简单的几项成就出时髦的风格。多层次的穿搭展现年轻化的流行感,细肩带上衣加背心、牛仔裤套短裙等只要是穿”与“搭”的

MINA框架新人指南

支付宝(中国)网络技术有限公司 蓝秋鹏(仲景)

目录 1.前言 (3) 2.实践 (4) 2.1.服务端演示 (4) 2.2.客户端演示 (6) 3.进阶 (8)

在资金线混有两个技术框架是一定要懂得如何使用的,它们就是MINA和HTTPCLIENT(还没听过的,就先百度一下)。支付宝和银行前置机之间的通讯基本都是使用者两种框架,即使你不懂SOCKET或者HTTP很底层的协议也没多大关系。 对于HTTPCLIENT有过很多实践了,从我刚进支付宝的第一个项目个人诚信通,到最近的建行境外收单直连改造,都是使用HTTP通讯。 突然间要做建行银行卡代扣,需要使用SOCKET跟建行通讯,对SOCKET 一点都不懂,只是听大禹和香石说使用MINA很简单,闭关修炼了两天确实很简单,哈哈。先找到MINA的主页,肯定有很多资料可以学习的,然后再编写DEMO,跑起来,改改DEMO,添加一些个性化的功能,两天时间基本上就算入门啦,可以开始进入项目编码啦。这些时间对于开发工程师来说,就是项目的技术准备阶段,在BRD或者PRD阶段投入的资源,让开发人员在开发阶段不再担心技术问题,可以快速编码,甚至提前完成开发任务。 跟MINA类似的框架,还有著名的Jboss Netty,代码框架非常类似,使用方法也大同小异,可以说Jboss Netty是MINA的改良版,但是目前我们系统还没有Jboss Netty的实际应用,不考虑引入到实际项目中。 本文档作为MINA框架的入门手册,浅显易懂,没有高级应用,比如配置线程模型,就可以满足日常开发。

跟银行的通讯,首先我们要定位自己的角色,我们扮演的是客户端,还是服务端,大部分场景我们都是扮演客户端的角色,如果银行有通知接口,在业务做完时银行会主动通知我们,推进我们的业务,这时我们就是服务端。 2.1.服务端演示 通过DEMO实现一个简单的服务端,MINA框架已经做了很好的封装,我们只需要编写几行代码,通过main启动MinaServer,监听端口1314: SOCKET接口是TCP/IP网络的API,不说这些很抽象的概念,我们可以直接使用MINA封装的SocketAcceptor 。 main方法中定义了整型的端口1314,在实际应用中一般通过antx.properties配置端口,这样就可以把配置的权限交给运维部门。 每一个信息都会通过在IoAcceptor中定义的过滤器链的所有过滤器,完成个性化的日志记录和解码工作。日志过滤器用SL4J库记录信息,而编码过滤器则解码所有收到的信息. 这个简单的例子,我们使用 new TextLineCodecFactory() 发送的信息进行编码,这是MINA自带的,功能有限,只能处理文本或者String类型。 还有一个参数new ServerHandler(),传的是实现IoHandler接口的类,对客户端的请求要进行什么业务处理,都在这里实现。

Java 远程通讯_MINA

第一章MINA前述 1.1线程模型 MINA线程模型采用了Reactors in threads模型,即Main Reactor + Sub Reactors的模式。由main reactor处理连接相关的任务:accept、connect等,当连接处理完毕并建立一个socket连接(称之为session)后,给每个session分配一个sub reactor,之后该session的所有IO、业务逻辑处理均交给了该sub reactor。每个reactor均是一个线程,sub reactor中只靠内核调度,没有任何通信且互不打扰。 现在来讲讲我对线程模型演进的一些理解: Thread per Connection:在没有nio之前,这是传统的java网络编程方案所采用的线程模型。即有一个主循环,socket.accept阻塞等待,当建立连接后,创建新的线程/从线程池中取一个,把该socket连接交由新线程全权处理。这种方案优缺点都很明显,优点即实现简单,缺点则是方案的伸缩性受到线程数的限制。 Reactor in Single Thread:有了nio后,可以采用IO多路复用机制了。我们抽取出一个单线程版的reactor模型,时序图见下文,该方案只有一个线程,所有的socket连接均注册在了该reactor上,由一个线程全权负责所有的任务。它实现简单,且不受线程数的限制。这种方案受限于使用场景,仅适合于IO密集的应用,不太适合CPU密集的应用,且适合于CPU资源紧张的应用上。 Reactor + Thread Pool:方案2由于受限于使用场景,但为了可以更充分的使用CPU资源,抽取出一个逻辑处理线程池。reactor仅负责IO任务,线程池负责所有其它逻辑的处理。虽然该方案可以充分利用CPU资源,但是这个方案多了进出thread pool的两次上下文切换。

MINA 框架简介

MINA 框架简介 2011-02-12 9:35 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并不适用。学习本文档,需要你已掌握JAVA IO、JAVA NIO、JAVASocket、JAVA 线程及并发库(java.util.concurrent.*)的知识。Mina 同时提供了网络通信的Server 端、Client 端的封装,无论是哪端,Mina 在整个网通通信结构中都处于如下的位置: 1。MINA 框架简介 当客户首次访问采用MINA编写的程序时,IoAcceptor作为线程运行,负责接受来自客户的请求。当有客户请求连接时,创建一个 Session,该Session与IoProcessor、SocketChannel以及IOService联系起来。IoProcessor也作为另外一个线程运行,定时检查客户是否有数据到来,并对客户请求进行处理,依次调用在IOService注册的各个IoFilter,最后调用 IoHandler进行最终的逻辑处理,再将处理后的结果Filter后返回给客户端。 2。IoSession Session可以理解为服务器与客户端的特定连接,该连接由服务器地址、端口以及客户端地址、端口来决定。客户端发起请求时,指定服务器地址和端口,客户端也会指定或者根据网络路由信息自动指定一个地址、自动分配一个端口。这个地址、端口对构成一个Session。 Session是服务器端对这种连接的抽象,MINA对其进行了封装,定义了IoSession 接口,用来代表客户端与服务器的连接,在服务器端来指代客户端,实现对客户端的操作、绑定与客户端有关的信息与对象。通过利用Session的这个概念,编写程序时就可以在服务器端非常方便地区分出是当前处理的是哪个客户端的请求、维持客户端的状态信息、可以实现客户端之间相互通讯。 IoSession提供以下一些常用方法: (1)setAttribute(Object key, Object value) getAttribute(Object key)

《GreenEggsAndHam》中文翻译

G r e e n E g g s A n d H a m IamSam我是山姆 SamIam山姆是我 ThatSam-I-am ThatSam-I-am那个“山姆是我” Idon’tlikeThatSam-I-am我不喜欢那个“山姆是我” Doyoulikegreeneggsandham?你喜欢绿鸡蛋和火腿吗? Idonotlikethem,Sam-I-am.?我不喜欢,山姆是我。 Idonotlikegreeneggsandham.我不喜欢绿鸡蛋和火腿。Wouldyoulikethemhereorthere? 你想在这儿还是那儿吃绿鸡蛋和火腿? Iwouldnotlikethemhereorthere.我不想在这儿吃,也不想在那儿吃Iwouldnotlikethemanywhere.我在哪儿都不想吃绿鸡蛋和火腿Idonotlikegreeneggsandham我不喜欢吃绿鸡蛋和火腿 Idonotlikethem,Sam-I-am我不喜欢他们,山姆是我。Wouldyouliketheminahouse?你想在房子里吃吗? Wouldyoulikethemwithamouse?你想和老鼠一起吃吗?

Idonotliketheminahouse我不想在房子里吃Idonotlikethemwithamouse也不想和老鼠一起吃Idonotlikethemhereorthere我既不想在这里吃,也不想在那里吃Idonotlikethemanywhere我在哪儿都不想吃绿鸡蛋和火腿Idonotlikegreeneggsandham我不喜欢吃绿鸡蛋和火腿Idonotlikethem,Sam-I-am我不喜欢他们,山姆是我Wouldyoueattheminabox?你想在盒子里吃吗?Wouldyoueatthemwithafox?你想和狐狸一起吃吗?Notinabox.Notwithafox.我不想盒子里吃.不和狐狸一起吃. Notinahouse.Notwithamouse.不在房子里吃.不和老鼠一起吃。Iwouldnoteatthemhereorthere我既不想在这里吃,也不想在那里吃Iwouldnoteatthemanywhere我在哪儿都不想吃Iwouldnoteatgreeneggsandham我不想吃绿鸡蛋和火腿Idonotlikethem,Sam-I-am我不喜欢它们,山姆是我Wouldyou?Couldyou?Inacar? 那你愿不愿意,要不要在车里吃? Eatthem!Eatthem!吃呀!吃呀!

AMS285-1.2BL中文资料

Advanced AMS285-1.2/AMS385-1.2 Monolithic MICROPOWER VOLTAGE REFERENCE DIODE Systems FEATURES APPLICATIONS ?±4 mV (±0.3%) max. initial tolerance (A grade)? Battery Powered Systems ? Operating Current 10μA to 20mA? Instrumentation ? Low Voltage Reference 1.235? A/D, D/A Converters ? Max. 0.6? Dynamic Impedance (A grade)? Temperature measurement ? Low Temperature Coefficient? Current sources ? 2.5V Device and Adjustable Device also available? Notebook/Personal Computer AMS285-2.5 and AMS285 series, respectively? Monitors/ VCR/ TV AMS385-2.5 and AMS385 series.? Pagers GENERAL DESCRIPTION The AMS285-1.2/AMS385-1.2 are two-terminal micropower band-gap voltage reference diodes. They feature a very low dynamic impedance and good temperature coefficient, operating over a 10μA to 20mA current range. On-chip trimming is used to provide tight voltage tolerance. Since the AMS285-1.2/AMS385-1.2 is a band-gap reference, uses only transistors and resistors, low noise and good long-term stability result. Careful design of the AMS285-1.2/AMS385-1.2 has made the device exceptionally tolerant of capacitive loading, making it easy to use in almost any reference application. The wide dynamic operating range allows its use with widely varying supplies with excellent regulation. The extremely low power drain of the AMS285-1.2/AMS385-1.2 makes these reference diodes useful for micropower circuitry. These voltage references can be used to make portable meters, regulators or general purpose analog circuitry with battery life approaching shelf life. Further more, the wide operating current allows it to replace older references with a tight tolerance part. The AMS285-1.2 is operational in the full industrial temperature range of -40°C to 85°C while AMS385-1.2 is operating over a 0°C to 70°C temperature range. The AMS285-1.2/AMS385-1.2 are available in TO-92, SO-8 and SOT-89 packages. ORDERING INFORMATION: TOL.PACKAGE TYPE OPERATING TO-928 LEAD SOIC SOT-89TEMPERATURE RANGE ±4mV AMS285-1.2AN AMS285-1.2AS AMS285-1.2AL-40 to 85° C ±12mV AMS285-1.2BN AMS285-1.2BS AMS285-1.2BL-40 to 85° C ±25mV AMS285-1.2CN AMS285-1.2CS AMS285-1.2CL-40 to 85° C ±4mV AMS385-1.2AN AMS385-1.2AS AMS385-1.2AL 0 to 70° C ±12mV AMS385-1.2BN AMS385-1.2BS AMS385-1.2BL 0 to 70° C ±25mV AMS385-1.2CN AMS385-1.2CS AMS385-1.2CL 0 to 70° C

相关文档