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

posted on   luzhouxiaoshuai  阅读(284)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示