Java SocketChannel 与 SocketChannel通信模板

本文介绍了如何使用Java中的Selector类实现并发服务器,通过非阻塞模式处理多个客户端连接,提高服务器性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[TOC]
抢先体验运行效果

Server

public class SelectorServer {
    private static Selector selector ;
    public static void main(String[] args) {
        ServerSocketChannel serverChannel = null;
        try {
            serverChannel = ServerSocketChannel.open();
            serverChannel.socket().setReuseAddress(true);
            serverChannel.socket().bind(new InetSocketAddress(3467));
            serverChannel.configureBlocking(false); // none blocking mode
            selector = SelectorProvider.provider()
                    .openSelector();
            Iterator<SelectionKey> selectorKeys = null;
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
            while (true) {
                // selector mode
                // 阻塞选择操作, n 已经准备好的通道的个数。
                int n = selector.select();
                if (n == 0) {
                    continue;
                }
                selectorKeys = selector.selectedKeys().iterator();
                SelectionKey oneKey = null; 
                while (selectorKeys.hasNext()) {
                    try{
                        oneKey = selectorKeys.next();
                        selectorKeys.remove();
                        handleSelectorKey(oneKey);
                    }finally{
                        try{
                            if(oneKey != null && oneKey.isWritable()){
                                oneKey.cancel();
                                oneKey.channel().close();
                            }
                        }catch(IOException e){
                            e.printStackTrace();
                        }

                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClosedSelectorException e) {
            e.printStackTrace();
        }
        finally {

        }

    }
    static ByteBuffer readerBuffer ;
    private synchronized static void handleSelectorKey(SelectionKey key) {
        if(key == null){
            return;
        }

        if (key.isAcceptable()) {
            System.out.println("selection acceptable --> " + key.isValid());
            handleSelectionAcceptable(key);
        }

        if (key.isConnectable()) {
            System.out.println("selection connectable --> " + key.isValid());
            handleSelectionAcceptable(key);
        }

        if (key.isReadable()) {
            System.out.println("selection readable --> " + key.isValid());
            synchronized (SelectorServer.class) {
                readerBuffer = handleSelectionReadable(key);
            }

        }

        if (key.isWritable()) {
            System.out.println("selection writeable --> " + key.isValid());
            synchronized (SelectorServer.class) {
            handleSelectionWriteable(key,readerBuffer);
            }
        }
    }

    public static void handleSelectionAcceptable(SelectionKey key) {
        if(key == null) return;
        try{
            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
            SocketChannel sc = (SocketChannel) ssc.accept();

            System.out.println("receive connection request " +
                    sc.socket().getInetAddress()+":"+sc.socket().getPort());

            sc.configureBlocking(false);
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.put("attachment added by myself .".getBytes());
            buffer.flip();
            sc.register(selector, SelectionKey.OP_READ,buffer);
        }catch(IOException e){

        }
    }

    public static void handleSelectionCollectable(SelectionKey key) {

    }

    public  static ByteBuffer handleSelectionReadable(SelectionKey key) {
        ByteBuffer buffer = (ByteBuffer) key.attachment();
        if(buffer != null){
            System.out.println("attachment data===== : " + getString(buffer));
            buffer.rewind();
        }
        SocketChannel sc = (SocketChannel) key.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        try {
            sc.read(readBuffer);
            sc.register(selector, SelectionKey.OP_WRITE,buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        readBuffer.flip();
        String data = getString(readBuffer);
        System.out.println("receive data from client --->: "
                + data+"  == "+ sc.socket().getInetAddress()
                +"  :"+sc.socket().getPort());
        readBuffer.rewind();
        return readBuffer;
    }

    public static String getString(ByteBuffer buffer)
    {
        if(buffer ==null){
            return "";
        }
        Charset charset = null;
        CharsetDecoder decoder = null;
        CharBuffer charBuffer = null;
        try
        {
            charset = Charset.forName("UTF-8");
            decoder = charset.newDecoder();
             charBuffer = decoder.decode(buffer);//用这个的话,只能输出来一次结果,第二次显示为空
            String s = charBuffer.toString();
            System.out.println("buffer to string : len : " + s.length() +"  ;data: " + s);
            return charBuffer.toString().trim();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return "";
        }
    }


    public  static void handleSelectionWriteable(SelectionKey key,ByteBuffer readBuffer) {
        String toClientData = "echo server : "+getString(readBuffer);
        byte serverEcho[] = toClientData.getBytes(Charset.forName("utf-8"));

        ByteBuffer writeBuffer = ByteBuffer.wrap(serverEcho);
        SocketChannel sc = (SocketChannel) key.channel();

        try {
            sc.write(writeBuffer);
            System.out.println("to client data--->: " + toClientData
                    +"  == "+ sc.socket().getInetAddress()
                    +"  :"+sc.socket().getPort());
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e);
        }finally {

        }
    }

}

client

public class SocketChannelClient extends Thread{
    public static final String SERVER_ADDRESS = "localhost";
    public static final int SERVER_PORT = 3467;
    private final String address;
    private final int port ;
    SocketChannel socketChannel;
    Selector selector;
    public SocketChannelClient(String remoteAdress , int remotePort){
        address = remoteAdress;
        port = remotePort;
    }


    public static void main(String[] args) {

        SocketChannelClient client = new SocketChannelClient(SocketChannelClient.SERVER_ADDRESS,
                 SocketChannelClient.SERVER_PORT);
         client.start();
    }
    @Override
    public void run() {
        try{
            socketChannel = SocketChannel.open(new InetSocketAddress(address,port));
            socketChannel.configureBlocking(false);
            selector = SelectorProvider.provider().openSelector();
            socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
            Iterator<SelectionKey> keyIterator;
            SelectionKey oneKey = null;
            while(true){
                int n = selector.select();
                if(n == 0){
                    continue;
                }
                keyIterator = selector.selectedKeys().iterator();
                while(keyIterator.hasNext()){
                    try{
                        oneKey = keyIterator.next();
                        keyIterator.remove();
                        handleSelectorKey(oneKey);
                    }finally{
                        try{
                            if(oneKey != null && oneKey.isReadable()){
                                oneKey.channel().close();
                                oneKey = null;
                            }
                        }catch(IOException e){
                            e.printStackTrace();
                        }

                    }
                }
            }

        }catch(IOException e){
            e.printStackTrace();
        }

    }
    private synchronized void handleSelectorKey(SelectionKey key) {
        if(key == null){
            return;
        }
        if (key.isAcceptable()) {
            System.out.println("selection acceptable --> " + key);
            handleSelectionAcceptable(key);
        }

        if (key.isConnectable()) {
            System.out.println("selection connectable --> " + key);
            handleSelectionAcceptable(key);
        }

        if (key.isReadable()) {
            System.out.println("selection readable --> " + key);
            handleSelectionReadable(key);
        }

        if (key.isWritable()) {
            System.out.println("selection writeable --> " + key);
            handleSelectionWriteable(key);
        }
    }

    public  void handleSelectionAcceptable(SelectionKey key) {
        if(key == null) return;
        try{
            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
            SocketChannel sc = (SocketChannel) ssc.accept();

            System.out.println("receive connection request " +
                    sc.socket().getInetAddress()+":"+sc.socket().getPort());

            sc.configureBlocking(false);
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            sc.register(selector, SelectionKey.OP_READ,buffer);
        }catch(IOException e){

        }
    }

    public  void handleSelectionCollectable(SelectionKey key) {

    }

    public  void handleSelectionReadable(SelectionKey key) {
        SocketChannel sc = (SocketChannel) key.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        try {
            sc.read(readBuffer);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

        }
        readBuffer.flip();
        System.out.println("receive data from server --->: "
                + getString(readBuffer));
    }
    public static String getString(ByteBuffer buffer)
    {
        Charset charset = null;
        CharsetDecoder decoder = null;
        CharBuffer charBuffer = null;
        try
        {
            charset = Charset.forName("UTF-8");
            decoder = charset.newDecoder();
            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
            return charBuffer.toString();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return "";
        }
    }
    static int talkValue = 0;
    ByteBuffer sendBuffer;
    public  void handleSelectionWriteable(SelectionKey key) {
         sendBuffer = ByteBuffer.wrap(("talk to server "+(++talkValue)).getBytes(Charset.forName("utf-8")));
        key.attach(sendBuffer);
        SocketChannel sc = (SocketChannel) key.channel();
        try {
            sc.write(sendBuffer);
            key.interestOps(SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值