[JAVA] J'ai essayé d'implémenter un serveur en utilisant Netty

en premier

La dernière fois, j'ai essayé de créer un chemin de transfert TCP / IP + NIO / BIO en utilisant des bibliothèques telles que webSocket et SocketChannel, mais j'ai trouvé que le code devenait assez compliqué. Cette fois, je vais essayer de réaliser à nouveau un serveur en utilisant Netty.

Qu'est-ce que Netty

En termes simples, Netty est un framework pour développer des applications qui communiquent de manière asynchrone. Par rapport au traitement NIO réalisé par SocketChannel, il n'est plus nécessaire d'exploiter directement les API de basse couche (select (), read (), etc.), et il est caché côté Netty.

la mise en oeuvre

Implémentation NIO sur ServerSocket Channel

Tout d'abord, je republierai la précédente implémentation NIO sur ServerSocket Channel.

➀ Créez un ServerSocketChannel et écoutez l'accès côté client


public class ChannelServer {

    public static void main(String[] args) throws IOException {
        // I/Préparer un pool de threads pour traiter les requêtes O
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 1000, TimeUnit.MILLISECONDS, 
                new ArrayBlockingQueue<Runnable>(100));

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(1234));

        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();

            if (socketChannel != null) {
                //Validez la demande dans le pool de threads
                executor.submit(new ChannelServerThread(socketChannel));
            }
        }
    }
}

② Thread pour traiter la demande


public class ChannelServerThread implements Runnable {

    private SocketChannel socketChannel;
    private String remoteName;

    public ChannelServerThread(SocketChannel socketChannel) throws IOException {
        this.socketChannel = socketChannel;
        this.remoteName = socketChannel.getRemoteAddress().toString();
        System.out.println("client:" + remoteName + " access successfully!");
    }

    // I/Gérer la demande O
    @Override
    public void run() {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        ByteBuffer sizeBuffer = ByteBuffer.allocate(4);
        StringBuilder sb = new StringBuilder();
        byte b[];
        //Lire les données et la longueur de socketChannel et sortie vers la sortie standard
        while(true) {
            try {
                sizeBuffer.clear();
                int read = socketChannel.read(sizeBuffer);
                if (read != -1) {
                    sb.setLength(0);
                    sizeBuffer.flip();
                    int size = sizeBuffer.getInt();
                    int readCount = 0;
                    b = new byte[1024];
                    while (readCount < size) {
                        buffer.clear();
                        read = socketChannel.read(buffer);
                        if (read != -1) {
                            readCount += read;
                            buffer.flip();
                            int index = 0 ;
                            while(buffer.hasRemaining()) {
                                b[index++] = buffer.get();
                                if (index >= b.length) {
                                    index = 0;
                                    sb.append(new String(b,"UTF-8"));
                                }
                            }
                            if (index > 0) {
                                sb.append(new String(b,"UTF-8"));
                            }
                        }
                    }
                    System.out.println(remoteName +  ":" + sb.toString());
                }
            } catch (Exception e) {
                System.out.println(remoteName + "access colsed");
                try {
                    socketChannel.close();
                } catch (IOException ex) {
                }
                break;
            }
        }
    }
}

Implémentation NIO avec Netty

➀ Traitement en attente d'accès côté client


public class EchoServer {
    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void start() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap sb = new ServerBootstrap();
            //Liaison de pool de threads
            sb.group(group)
                    .channel(NioServerSocketChannel.class)
                     //Liaison de numéro de port
                    .localAddress(this.port)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            System.out.println("connected...; Client:" + ch.remoteAddress());
                            ch.pipeline().addLast(new EchoServerHandler());
                        }
                    });
            //Liaison asynchrone du serveur
            ChannelFuture cf = sb.bind().sync();
            System.out.println(EchoServer.class + " started and listen on " + cf.channel().localAddress());
            //Fermer le canal du serveur
            cf.channel().closeFuture().sync();
        } finally {
            //Dissocier le pool de threads
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws Exception {
        //entrée
        new EchoServer(66666).start();
    }
}

② Celui qui traite la demande


public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("server channelRead...; received:" + msg);
        ctx.write(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("server channelReadComplete..");
        //WriteAndFlush dans un tampon vide,Fermer la connexion
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("server occur exception:" + cause.getMessage());
        cause.printStackTrace();
        ctx.close();
    }
}

point de changement

** La quantité de code a été considérablement réduite. ** ** Cela permet de masquer les API telles que les opérations read () et Buffer du côté Netty et de fournir une API de couche supérieure pratique. Par exemple, la méthode channelRead () de la classe EchoServerHandler: lorsque les données du côté client sont reçues, elles sont converties en interne en String, cette méthode est donc appelée.

Résumé

Cette fois, j'ai essayé d'implémenter le serveur en utilisant Netty. Je présenterai la coopération avec le client la prochaine fois.

Recommended Posts

J'ai essayé d'implémenter un serveur en utilisant Netty
J'ai essayé d'utiliser Log4j2 sur un serveur Java EE
J'ai essayé d'utiliser le référentiel GitHub comme serveur de bibliothèque
J'ai essayé d'implémenter une application web pleine de bugs avec Kotlin
J'ai essayé d'implémenter le modèle Iterator
[Unity] J'ai essayé de créer un plug-in natif UniNWPathMonitor en utilisant NWPathMonitor
J'ai essayé de créer une application simple en utilisant Dockder + Rails Scaffold
J'ai essayé de créer une simple application Android de reconnaissance faciale en utilisant OpenCV
J'ai essayé d'utiliser Gson
java j'ai essayé de casser un simple bloc
[Rails] J'ai essayé d'implémenter une transaction qui combine plusieurs processus DB
J'ai essayé de développer un outil de gestion des effectifs
J'ai essayé de développer un site Web pour étudier DUO3.0.
J'ai essayé de créer une application de clonage LINE
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
J'ai essayé de développer un site Web pour enregistrer les dépenses.
J'ai essayé de casser le bloc avec java (1)
J'ai essayé d'implémenter une fonction équivalente à Felica Lite avec HCE-F d'Android
[Java] J'ai essayé de me connecter en utilisant le pool de connexion avec Servlet (tomcat) & MySQL & Java
J'ai essayé d'utiliser une connexion à une base de données dans le développement Android
J'ai essayé d'utiliser la fonction Server Push de Servlet 4.0
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
J'ai essayé d'implémenter la notification push Firebase en Java
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
J'ai essayé de créer une compétence Clova en Java
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé d'implémenter Sterling Sort avec Java Collector
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
J'ai essayé de gratter un graphique boursier en utilisant Java (Jsoup)
J'ai essayé d'utiliser azure cloud-init
J'ai essayé d'utiliser Apache Wicket
J'ai essayé de vérifier yum-cron
J'ai essayé d'utiliser Wercker pour créer et publier une image Docker qui lance GlassFish 5
Je souhaite l'implémenter en plus lors de l'utilisation de kotlin sur un site exécutant Java
J'ai essayé d'implémenter la fonction similaire par communication asynchrone
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé d'ajouter une ligne de séparation à TabLayout sur Android
J'ai essayé de moderniser une application Java EE avec OpenShift.
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Je souhaite implémenter une fonction d'édition des informations produit ~ part1 ~
J'ai essayé de lier le chat avec le serveur de Minecraft avec l'API Discord
J'ai essayé de construire l'environnement petit à petit en utilisant docker
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices
J'ai créé un client RESAS-API en Java
J'ai essayé de créer un environnement de développement padrino avec Docker
J'ai essayé de démarrer avec Swagger en utilisant Spring Boot
J'ai créé un Dockerfile pour démarrer Glassfish 5 en utilisant Oracle Java
J'ai essayé d'utiliser anakia + Jing maintenant