java异步网络io和tcp,JavaAIO初探(异步网络IO)

绑定本地地址:

this.serverSocketChannel。bind(new InetSocketAddress("localhost",8080), 100);其中的100用于指定等待连接的队列大小(backlog)。完了吗?还没有,重要的监听工作还没开始,监听端口是为了等待连接上来以便 accept产生一个AsynchronousSocketChannel来表示一个新建立的连接,因此需要发起一个accept调用,调用是异步的,操作系统将在连接建立后,将后的结果——AsynchronousSocketChannel返回给你:

public void pendingAccept(){

if (this.started  this.serverSocketChannel.isOpen()) { this.acceptFuture = this.serverSocketChannel.accept(null,

new AcceptCompletionHandler());

} else {

throw new IllegalStateException("Controller has been closed");

}

注意,重复的accept调用将会抛出PendingAcceptException,后文提到的read和write也是如此。accept方法的个参数是你想传给CompletionHandler的attchment,第二个参数就是注册的用于回调的CompletionHandler,后返回结果Future.你可以对future做处理,这里采用更推荐的方式就是注册一个CompletionHandler.那么accept的 CompletionHandler中做些什么工作呢?显然一个赤裸裸的AsynchronousSocketChannel是不够的,我们需要将它封装成session,一个session表示一个连接(mina里就叫IoSession了),里面带了一个缓冲的消息队列以及一些其他资源等。在连接建立后,除非你的服务器只准备接受一个连接,不然你需要在后面继续调用pendingAccept来发起另一个accept请求:

private final class AcceptCompletionHandler implements

CompletionHandler {

@Override

public void cancelled(Object attachment){

logger.warn("Accept operation was canceled");

}

@Override

public void completed(AsynchronousSocketChannel socketChannel,

Object attachment){

try {

logger.debug("Accept connection from " + socketChannel.getRemoteAddress());

configureChannel(socketChannel);

AioSessionConfig sessionConfig = buildSessionConfig(socketChannel);

Session session = new AioTCPSession(sessionConfig,AioTCPController.this.configuration。 getSessionReadBufferSize(),AioTCPController.this.sessionTimeout);session.start();

registerSession(session);

} catch(Exception e){

e.printStackTrace();logger.error("Accept error", e);

notifyException(e);

} finally {

pendingAccept();

}

@Override

public void failed(Throwable exc, Object attachment) { logger.error("Accept error", exc);

try {

notifyException(exc);

} finally {

pendingAccept();

}

注意到了吧,我们在failed和completed方法中在后都调用了pendingAccept来继续发起accept调用,等待新的连接上来。有的同学可能要说了,这样搞是不是递归调用,会不会堆栈溢出?实际上不会,因为发起accept调用的线程与CompletionHandler回调的线程并非同一个,不是一个上下文中,两者之间没有耦合关系。要注意到,CompletionHandler的回调共用的是 AsynchronousChannelGroup绑定的线程池,因此千万别在回调方法中调用阻塞或者长时间的操作,例如sleep,回调方法能支持超时,防止线程池耗尽。

连接建立后,怎么读和写呢?回忆下在nonblocking nio框架中,连接建立后的件事是干什么?注册OP_READ事件等待socket可读。异步IO也同样如此,连接建立后马上发起一个异步read调用,等待socket可读,这个是Session.start方法中所做的事情:

public class AioTCPSession {

protected void start0(){

pendingRead();

}

protected final void pendingRead(){

if (!isClosed()  this.asynchronousSocketChannel.isOpen()) { if (!this.readBuffer.hasRemaining()) { this.readBuffer = ByteBufferUtils。increaseBufferCapatity(this.readBuffer);

}

来源:考试大-Java认证

责编:zj  评论 纠错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值