• java scoket aIO 通信


    AsynchronousServerSocketChannel

    assc.accept(this, new ServerCompletionHandler()); 第一个参数是服务器的处理类,第二个参数当服务接受到客户端的连接之后,用来处理客户端的连接

    这里accept并不是一直阻塞的,会继续向下面执行,为了保证服务器端程序一直运行存在,所以这里使用了

    //进行阻塞。第一个参数可以是null
    assc.accept(this, new ServerCompletionHandler());
    //一直阻塞 不让服务器停止
    Thread.sleep(Integer.MAX_VALUE);

    this就是当前的服务器端的实例对象,ServerCompletionHandler用来处理客户端请求数据的,必须实现implements CompletionHandler<AsynchronousSocketChannel, Server>

    第一个参数AsynchronousSocketChannel就是当前服务器端的Channel通道对象,第二参数和assc.accept(this, new ServerCompletionHandler());中的第一个参数必须一一对应

    实现CompletionHandler接口必须实现下面的两个方法

    completed

    failed

    @Override
    public void completed(AsynchronousSocketChannel asc, Server attachment) {
    //当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞
    attachment.assc.accept(attachment, this);
    read(asc);
    }

    attachment就是传递进来的服务器对象,attachment.assc就是Server类的channel对象,然后在调用channel对象对象的accept对象,就和在server端调用assc.accept(this, new ServerCompletionHandler());一样

    在 completed函数中进行递归调用assc.accept(this, new ServerCompletionHandler())

    接下来就可以读取客户端连接的数据了read(asc);

    来一个客户端就调用一次assc.accept(this, new ServerCompletionHandler()),所以在在 completed函数中进行递归调用assc.accept(this, new ServerCompletionHandler())进行递归调用

    我们来看下客户端服务器的代码:

    package bhz.aio;
    
    import java.net.InetSocketAddress;
    import java.nio.channels.AsynchronousChannelGroup;
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Server {
        //线程池
        private ExecutorService executorService;
        //线程组
        private AsynchronousChannelGroup threadGroup;
        //服务器通道
        public AsynchronousServerSocketChannel assc;
        
        public Server(int port){
            try {
                //创建一个缓存池
                executorService = Executors.newCachedThreadPool();
                //创建线程组,1表示初始化一个线程池
                threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);
                //创建服务器通道
                assc = AsynchronousServerSocketChannel.open(threadGroup);
                //进行绑定,这里就没有nio的seletor操作
                assc.bind(new InetSocketAddress(port));            
                System.out.println("server start , port : " + port);
                //进行阻塞。第一个参数可以是null
                assc.accept(this, new ServerCompletionHandler());
                //一直阻塞 不让服务器停止
                Thread.sleep(Integer.MAX_VALUE);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        public static void main(String[] args) {
            Server server = new Server(8765);
        }
        
    }
    package bhz.aio;
    
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.util.concurrent.ExecutionException;
    
    public class ServerCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {
    
        @Override
        public void completed(AsynchronousSocketChannel asc, Server attachment) {
            //当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞
            attachment.assc.accept(attachment, this);
            read(asc);
        }
    
        //AsynchronousSocketChannel客户端的通道
        private void read(final AsynchronousSocketChannel asc) {
            //读取数据,异步的读取数据
            ByteBuffer buf = ByteBuffer.allocate(1024);
            asc.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer resultSize, ByteBuffer attachment) {
                    //进行读取之后,重置标识位
                    attachment.flip();
                    //获得读取的字节数
                    System.out.println("Server -> " + "收到客户端的数据长度为:" + resultSize);
                    //获取读取的数据
                    String resultData = new String(attachment.array()).trim();
                    System.out.println("Server -> " + "收到客户端的数据信息为:" + resultData);
                    String response = "服务器响应, 收到了客户端发来的数据: " + resultData;
                    write(asc, response);
                }
                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    exc.printStackTrace();
                }
            });
        }
        
        private void write(AsynchronousSocketChannel asc, String response) {
            try {
                ByteBuffer buf = ByteBuffer.allocate(1024);
                buf.put(response.getBytes());
                buf.flip();
                asc.write(buf).get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        
        @Override
        public void failed(Throwable exc, Server attachment) {
            exc.printStackTrace();
        }
    
    }
    package bhz.aio;
    
    import java.io.UnsupportedEncodingException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.util.concurrent.ExecutionException;
    
    public class Client implements Runnable{
    
        private AsynchronousSocketChannel asc ;
        
        public Client() throws Exception {
            asc = AsynchronousSocketChannel.open();
        }
        
        public void connect(){
            asc.connect(new InetSocketAddress("127.0.0.1", 8765));
        }
        
        public void write(String request){
            try {
                asc.write(ByteBuffer.wrap(request.getBytes())).get();
                read();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private void read() {
            ByteBuffer buf = ByteBuffer.allocate(1024);
            try {
                asc.read(buf).get();
                buf.flip();
                byte[] respByte = new byte[buf.remaining()];
                buf.get(respByte);
                System.out.println(new String(respByte,"utf-8").trim());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        
        @Override
        public void run() {
            while(true){
                
            }
        }
        
        public static void main(String[] args) throws Exception {
            Client c1 = new Client();
            c1.connect();
            
            Client c2 = new Client();
            c2.connect();
            
            Client c3 = new Client();
            c3.connect();
            
            new Thread(c1, "c1").start();
            new Thread(c2, "c2").start();
            new Thread(c3, "c3").start();
            
            Thread.sleep(1000);
            
            c1.write("c1 aaa");
            c2.write("c2 bbbb");
            c3.write("c3 ccccc");
        }
        
    }

    程序运行的结果是:

    服务器响应, 收到了客户端发来的数据: c1 aaa
    服务器响应, 收到了客户端发来的数据: c2 bbbb
    服务器响应, 收到了客户端发来的数据: c3 ccccc

  • 相关阅读:
    xshell5连接虚拟机的小问题处理
    centos下安装python的过程
    windows下安装配置redis
    Mysql 插入修改报Incorrect string value: 'xE7xACxAC' for column 'DetectionResult' at row 1错误
    MD5 以key和iv保存 FormsAuthentication.HashPasswordForStoringInConfigFile过时的问题
    The user specified as a definer ('root'@'%') does not exist的解决方法
    C#判断字符串中包含某个字符的个数
    jquery easyui datagrid 在翻页以后仍能记录被选中的行及刷新设置选中行数据
    bat批处理删除多少天前的文件
    C# 获取系统字体方法
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/7723263.html
Copyright © 2020-2023  润新知