东山明月

V1

2022/04/18阅读:23主题:蓝莹

1. netty基本组件

本系列文章记录《Java读源码之Netty深入剖析》课程的学习过程。

本篇记录第二章的学习内容,以一个Socket例子为基础引出netty的各个组件。

1. socket例子!

这是一个简单的socket案例,实现服务端与客户端的通信,程序调用关系如下:

其中ServerBoot负责启动服务端,Client负责启动客户端。以下分别介绍各部分代码。

public class ServerBoot {

    private static final int PORT = 8000;

    public static void main(String[] args) {
        Server server = new Server(PORT);//调用Server启动服务端
        server.start();
    }

}
public class Server {

    private ServerSocket serverSocket;

    public Server(int port) {
        try {
            this.serverSocket = new ServerSocket(port);
            System.out.println("服务端启动成功,端口:" + port);
        } catch (IOException exception) {
            System.out.println("服务端启动失败");
        }
    }

    public void start() {
        new Thread(new Runnable() { //单独起一个线程,不至于主线程阻塞
            @Override
            public void run() {
                doStart();
            }
        }).start();
    }

    private void doStart() {
        while (true) {
            try {
                //用于处理客户端的连接
                Socket client = serverSocket.accept(); 
                //具体处理细节交由ClientHandler完成
                new ClientHandler(client).start();
            } catch (IOException e) {
                System.out.println("服务端异常");
            }
        }
    }
}
public class ClientHandler {

    public static final int MAX_DATA_LEN = 1024;
    private final Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    public void start() {
        System.out.println("新客户端接入");
        new Thread(new Runnable() {
            @Override
            public void run() {
                doStart();
            }
        }).start();
    }

    private void doStart() {
        try {
            InputStream inputStream = socket.getInputStream();
            while (true) {
                byte[] data = new byte[MAX_DATA_LEN];
                int len;
                while ((len = inputStream.read(data)) != -1) {
                    String message = new String(data, 0, len);
                    System.out.println("客户端传来消息: " + message);
                    socket.getOutputStream().write(data);
                }

            }


        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class Client {
    private static final String HOST = "127.0.0.1";
    private static final int PORT = 8000;
    private static final int SLEEP_TIME = 5000;

    public static void main(String[] args) throws IOException {
        final Socket socket = new Socket(HOST, PORT);

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("客户端启动成功!");
                while (true) {
                    try {
                        String message = "hello world";
                        System.out.println("客户端发送数据: " + message);
                        socket.getOutputStream().write(message.getBytes());
                    } catch (Exception e) {
                        System.out.println("写数据出错!");
                    }
                    sleep();
                }


            }
        }).start();

    }

    private static void sleep() {
        try {
            Thread.sleep(SLEEP_TIME);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下所示:

小结:以上例子完成服务端与客户端的通信,为netty的学习打下基础。netty框架细节再复杂,其完成的功能也与上述程序类似,之后可将netty的组件与上述程序中的代码对应,快速入门netty。

2. netty基本组件

  • NioEventLoop,会启动两种类型线程,分别监听客户端的连接、处理客户端的读写。对应于Socket例子中的Server类。
  • Channel,对连接的封装,在封装内可以完成对数据的读写,相当于Socket例子中new一个ServerSocket,并以此为基础进行数据读写。
  • Pipeline,数据读写的逻辑链。
  • ChannelHandler,数据读写具体的逻辑,对应于Socket例子中接收客户端信息并直接将其返回的代码逻辑。
  • ByteBuf,每个逻辑链内对数据的读写均是基于ByteBuf完成的,在Socket例子中的以byte数组进行数据读写的操作,这里的ByteBuf的作用与其类似。

分类:

后端

标签:

Java

作者介绍

东山明月
V1