Java7 nio2 异步Socket实践

1.写在前面

十年前就有高人在Windows上面用VC++写的高并发Tcp服务器程序,运用IOCP,异步Socket实现,可谓运用的淋漓尽致,即便是.Net中最新的Socket异步通信也只可能达到了这个的水平,而Java7中AsynchronousServerSocket还停留在.Net中Begin/End模式的时代,或许是专业领域不同吧,通用的软件库不会在某一个领域过于深入。
当然.Net与Java比C++上面实现,容易多了。
那个作者要是没有搞错的话就是他了: http://blog.csdn.net/sodme

2.基本思路

本人学识有限,多多指正
线程池执行所有的任务,线程池相对与一个线程维护一个连接可以减少线程本身对资源的消耗,如线程切换时CPU的消耗,线程本身内存占用。
异步IO操作就是,IO操作的发起与结束是分离的,发起IO操作以后中间不需要等待IO操作的完成,最好的处理方式就是是提交IO操作到线程池并且传递一个完成后的用于通知的完成方法。.Net中begin/end模式就是这样子的,Java中AsynchonousServerSocketChannel也是这样的。
begin/end模式通常简单用法,begin被第一次在初始化地方发起以后,当end响应以后,在end结尾处继续begin,更加开发的方式是,一次发起较多begin,然后用列表来管理,性能可能会更好,但是收到数据的顺序可能需要维护了。本文所述是单次begin/end方式。

3.代码示例

文件有两份

AsynchonousSocketClient.java

package FirstExercise;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;

public class AsynchronousSocketClient {

    private final AsynchronousSocketChannel asynchronousSocketChannel;
    private final String address;
    private final ByteBuffer byteBuffer;

    public AsynchronousSocketClient(String address, AsynchronousSocketChannel asynchronousSocketChannel) {
        this.asynchronousSocketChannel = asynchronousSocketChannel;
        this.address = address;

        byteBuffer = ByteBuffer.allocateDirect(16 * 1024);
    }

    public AsynchronousSocketChannel getAsynchronousSocketChannel() {
        return asynchronousSocketChannel;
    }

    public String getAddress() {
        return address;
    }

    public ByteBuffer getByteBuffer() {
        return byteBuffer;
    }
}

AsynchonousSocketServer.java

package FirstExercise;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ConcurrentHashMap;

public class AsynchronousSocketService {

    private final String host;
    private final int port;
    private AsynchronousServerSocketChannel asynchronousServerSocketChannel;

    ConcurrentHashMap<String, AsynchronousSocketClient> clientMap;

    public AsynchronousSocketService(String host, int port) {
        this.host = host;
        this.port = port;

        clientMap = new ConcurrentHashMap<>();
    }

    public void start() {
        try {
            SocketAddress localAddress = new InetSocketAddress(host, port);
            asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
            asynchronousServerSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            asynchronousServerSocketChannel.bind(localAddress, 100);
            asynchronousServerSocketChannel.accept(null, new AcceptCompletionHandler());

            System.out.println("Start AsynchronousSocketService " + localAddress);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stop() {
        try {
            if (asynchronousServerSocketChannel != null) {
                asynchronousServerSocketChannel.close();
                asynchronousServerSocketChannel = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        clientMap.forEach((x, y) -> {
            try {
                if (y != null) y.getAsynchronousSocketChannel().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        clientMap.clear();

        System.out.println("Stop AsynchronousSocketService");
    }

    class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {

        @Override
        public void completed(AsynchronousSocketChannel result, Object attachment) {
            try {
                AsynchronousSocketClient client = new AsynchronousSocketClient(
                        result.getRemoteAddress().toString(), result);
                clientMap.put(client.getAddress(), client);
                result.read(client.getByteBuffer(), client, new ReadCompletionHandler());
                System.out.println("Accept Client\t\t" + client.getAddress());

                asynchronousServerSocketChannel.accept(null, new AcceptCompletionHandler());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("Accept Exception");
        }
    }

    class ReadCompletionHandler implements CompletionHandler<Integer, Object> {

        @Override
        public void completed(Integer result, Object attachment) {
            AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
            AsynchronousSocketChannel channel = client.getAsynchronousSocketChannel();
            ByteBuffer byteBuffer = client.getByteBuffer();

            if (result <= 0) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("Close Client " + client.getAddress());
                clientMap.remove(client.getAddress());
                return;
            }

            System.out.printf("Read\t%d\tfrom\t%s\n", result, client.getAddress());

            byteBuffer.flip();
            channel.write(byteBuffer, client, new WriteCompletionHandler());

            byteBuffer.clear();
            channel.read(byteBuffer, client, new ReadCompletionHandler());
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
            System.out.printf("Read Exception %s\n", client.getAddress());
        }
    }

    class WriteCompletionHandler implements CompletionHandler<Integer, Object> {

        @Override
        public void completed(Integer result, Object attachment) {
            AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
            System.out.printf("Write\t%d\tto\t\t%s\n", result, client.getAddress());
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
            System.out.printf("Write Exception %s\n", client.getAddress());
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值