Essayez d'implémenter TCP / IP + NIO avec JAVA

Cet article utilise Java 10.0.1 installé sur WIN10.

en premier

La dernière fois j'ai fait un chemin de transfert BIO, aujourd'hui je vais continuer à implémenter NIO.

À propos de NIO

Qu'est-ce que NIO

En termes simples, il ne bloque pas les demandes d'E / S. Vous pouvez améliorer le traitement des E / S (BIO) existant.

Mauvais points de BIO

Tout d'abord, la demande du côté client comprend deux parties, une demande de connexion et une demande d'E / S. Les demandes de connexion sont toujours effectuées, mais des demandes d'E / S sont effectuées de temps en temps. Par conséquent, la méthode de préparation d'un thread de traitement indépendamment d'une demande, qu'il y ait ou non un traitement d'E / S tel que BIO gaspille les performances du serveur.

Bons points de NIO

NIO n'a qu'un seul thread de traitement pour chaque demande du côté client. S'il y a une demande d'E / S, demandez à un autre thread de traiter les E / S.

la mise en oeuvre

*** SocketChannel *** et *** ServerSocketChannel *** sont fournis à partir du langage Java, donc cette fois je vais essayer d'implémenter TCP / IP + NIO en utilisant ces derniers. (L'API officielle est ici: SocketChannel, [ServerSocketChannel](https: // docs .oracle.com / javase / jp / 8 / docs / api / java / nio / channels / ServerSocketChannel.html) Fichiers côté serveur

** Contenu de ChannelServer.java **

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));
            }
        }
    }
}

** Contenu de ChannelServer.java **

*** Fil de discussion 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;
            }
        }
    }
}

** Fichiers côté client **

*** Créez un socketChannel pour accéder au serveur et au port spécifiés ***

public class ChannelClient {

    public static void main(String[] args) throws IOException {

        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress(1234));
        while (true) {
            Scanner sc = new Scanner(System.in);
            String next = sc.next();
            sendMessage(socketChannel, next);
        }
    }

    //Préparer un conteneur pour Channel to IPO
    public static void sendMessage(SocketChannel socketChannel, String mes) throws IOException {
        if (mes == null || mes.isEmpty()) {
            return;
        }
        byte[] bytes = mes.getBytes("UTF-8");
        int size = bytes.length;
        ByteBuffer buffer = ByteBuffer.allocate(size);
        ByteBuffer sizeBuffer = ByteBuffer.allocate(4);

        sizeBuffer.putInt(size);
        buffer.put(bytes);

        buffer.flip();
        sizeBuffer.flip();
        ByteBuffer dest[] = {sizeBuffer,buffer};
        while (sizeBuffer.hasRemaining() || buffer.hasRemaining()) {
            socketChannel.write(dest);
        }
    }
}

Authentification des résultats

*** Démarrage du serveur et attente d'une connexion: ***

serveur

PS C:\Users\ma\Documents\work\socket\nio_tcp> java ChannelServer

*** Lancez respectivement les clients 1 et 2 et entrez quelque chose: ***

** Client 1 **


PS C:\Users\ma\Documents\work\socket\nio_tcp> java ChannelClient
iamfirstuser!
byebyefirstone!
Exception in thread "main"
PS C:\Users\ma\Documents\work\socket\nio_tcp>

** Client 2 **

java ChannelClient
iamseconduser
byebyesecondone!
Exception in thread "main"
PS C:\Users\ma\Documents\work\socket\nio_tcp>

serveur


PS C:\Users\ma\Documents\work\socket\nio_tcp> java ChannelServer
client:/192.168.56.1:50138 access successfully!
client:/192.168.56.1:50139 access successfully!
/192.168.56.1:50138:iamfirstuser!
/192.168.56.1:50139:iamseconduser
/192.168.56.1:50138:byebyefirstone!
/192.168.56.1:50138access colsed
/192.168.56.1:50139:byebyesecondone!
/192.168.56.1:50139access colsed

Résumé

Cette fois, j'ai créé un chemin de transfert TCP / IP + NIO en utilisant les bibliothèques Java SocketChannel et ServerSocketChannel. Nous avons également pu authentifier qu'un serveur peut traiter plusieurs demandes en même temps.

Recommended Posts

Essayez d'implémenter TCP / IP + NIO avec JAVA
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
[Java] Essayez de mettre en œuvre à l'aide de génériques
Essayez d'implémenter Yuma en Java
Essayez d'implémenter l'ajout n-aire en Java
Essayez d'implémenter une fonction de connexion avec Spring-Boot
Essayez d'intégrer Ruby et Java avec Dapr
Essayez d'implémenter la fonction de connexion avec Spring Boot
J'ai essayé d'implémenter Sterling Sort avec Java Collector
Java pour jouer avec Function
Essayez la connexion DB avec Java
Essayez gRPC avec Java, Maven
Connectez-vous à DB avec Java
Connectez-vous à MySQL 8 avec Java
[Java] Comment implémenter le multithreading
Je veux implémenter diverses fonctions avec kotlin et java!
Java pour apprendre avec les ramen [Partie 1]
[Java EE] Implémenter le client avec WebSocket
Essayez d'implémenter Yuma dans Ruby
[Java] Points à noter avec Arrays.asList ()
Essayez d'implémenter la fonction Widget iOS14
Osez défier Kaggle avec Java (1)
Essayez d'utiliser Redis avec Java (jar)
J'ai essayé d'interagir avec Java
Essayez d'extraire la méthode publique de java
Essayez la communication bidirectionnelle avec gRPC Java
Java, des tableaux pour débuter avec les débutants
Essayez d'accélérer le démarrage des programmes de console Java avec l'image native de GraalVM
Interface Essayez de créer un problème Java TypeScript 7-3
Comment implémenter le calcul de la date en Java
Essayez de résoudre Project Euler en Java
Comment compiler Java avec VsCode & Ant
[Java] Résumez comment comparer avec la méthode equals
Essayons WebSocket avec Java et javascript!
Introduction aux algorithmes avec java-Search (recherche prioritaire en profondeur)
Comment appliquer les conventions de codage en Java
Comment implémenter TextInputLayout avec la fonction de validation
Essayez de gérer les bibliothèques Java avec AWS CodeArtifact
Facile à parcourir avec les expressions régulières Java
Essayez d'utiliser la télécommande Wii en Java
Introduction aux algorithmes avec java --Search (recherche de priorité de largeur)
Essayez de vous connecter à la base de données autonome avec JDK6 (Java) + pilote JDBC OCI (type 2).
Défi pour gérer les caractères déformés avec Java AudioSystem.getMixerInfo ()
Écrivons l'entrée / sortie de fichier Java avec NIO
[Java] Comment tester s'il est nul dans JUnit
Essayez de créer un environnement Java 8 sur Amazon Linux2
J'ai essayé de faire une authentification de base avec Java
Introduction aux algorithmes avec java --Search (bit full search)
Déployez des applications Web Java sur Azure avec maven
Essayez de créer un babillard en Java
Comment utiliser le framework Java avec AWS Lambda! ??
Comportement incrémenté Essayez de créer un problème Java TypeScript 3-4
Je veux utiliser java8 forEach avec index
Opération de chaîne de caractères Essayez de changer le problème Java en TypeScript 9-3
Comment utiliser l'API Java avec des expressions lambda
Premiers pas avec Kotlin à envoyer aux développeurs Java