portaldacalheta.pt
  • Principal
  • Gestion De L'ingénierie
  • Gestion De Projet
  • Autre
  • Les Tendances
Back-End

Implémentation d'un serveur Framebuffer distant en Java



En informatique, Virtual Network Computing (VNC) est un système de partage de bureau graphique qui utilise le protocole Remote Framebuffer (RFB) pour contrôler à distance un autre ordinateur. Il transmet les événements du clavier et de la souris d'un ordinateur à un autre et relaie les mises à jour de l'écran graphique dans l'autre sens sur un réseau.

RFB est un protocole simple d'accès à distance aux interfaces utilisateur graphiques. Comme il fonctionne au niveau du tampon de trame, il est applicable à tous les systèmes et applications de fenêtrage, y compris Microsoft Windows, Mac OS X et X Window System.



Création d



Création d'une application Swing basée sur le protocole côté serveur Remote Framebuffer en Java Tweet

Dans cet article, je vais montrer comment implémenter le protocole côté serveur RFB et démontrer avec une petite application Java Swing comment transmettre la fenêtre principale via une connexion TCP aux visionneuses VNC. L'idée est de démontrer les fonctionnalités de base du protocole et l'implémentation possible en Java.



Le lecteur doit avoir une connaissance de base du langage de programmation Java et doit être familiarisé avec les concepts de base de la mise en réseau TCP / IP, du modèle client-serveur, etc. Idéalement, le lecteur est un Développeur Java et possède une certaine expérience des implémentations VNC bien connues telles que RealVNC, UltraVNC, TightVNC, etc.

Spécification du protocole Remote Framebuffer

La spécification du protocole RFB est jolie bien défini . Selon Wikipedia, le protocole RFB a plusieurs versions. Pour cet article, nous nous concentrerons sur les messages courants qui doivent être correctement compris par la plupart des implémentations VNC, quelle que soit la version du protocole.



Après qu'un visualiseur VNC (client) a établi une connexion TCP à un serveur VNC (service RFB), la première phase implique l'échange de la version du protocole:

RFB Service ----------- 'RFB 003.003 ' -------> VNC viewer RFB Service <---------- 'RFB 003.008 ' -------- VNC viewer

C'est un simple flux d'octets qui peut être décodé en Caractères ASCII , comme «RFB 003.008 n».



Une fois que cela est fait, l'étape suivante est l'authentification. Le serveur VNC envoie un tableau d'octets pour indiquer le type d'authentification qu'il prend en charge. Par exemple:

RFB Service ----------- 0x01 0x02 -----------> VNC viewer RFB Service <----------- 0x02 ----------- VNC viewer

Ici, le serveur VNC n'a envoyé qu'un seul type d'authentification possible (0x02). Le premier octet 0x01 indique le nombre de types d'authentification disponibles. Le visualiseur VNC doit répondre avec la valeur 0x02, car c'est le seul type possible pris en charge par le serveur dans cet exemple.



Ensuite, le serveur enverra un défi d'authentification (selon l'algorithme, il y en a plusieurs), et le client doit répondre avec un message de réponse de défi approprié et attendre que le serveur confirme la réponse. Une fois le client authentifié, il peut poursuivre le processus d'établissement de session.

Le moyen le plus simple ici est de ne choisir aucune authentification. Le protocole RFB n'est de toute façon pas sécurisé, quel que soit le mécanisme d'authentification. Si la sécurité est importante, la bonne façon serait de tunneliser les sessions RFB via des connexions VPN ou SSH.



À ce stade, la visionneuse VNC envoie un message de bureau partagé qui indique si le client partagera et autorisera d'autres visionneuses VNC à se connecter au même bureau. C'est à la mise en œuvre du service RFB de prendre en compte ce message et éventuellement d'empêcher plusieurs téléspectateurs VNC de partager le même écran. Ce message ne mesure que 1 octet et une valeur valide est 0x00 ou 0x01.

Enfin, le serveur RFB envoie un message d'initialisation du serveur, qui contient la dimension de l'écran, les bits par pixel, la profondeur, le drapeau big endian et les drapeaux de couleurs vraies, les valeurs maximales pour les couleurs rouge, verte et bleue, les positions des bits en pixel pour les couleurs rouge, vert et bleu , et chaîne / titre du bureau. Les deux premiers octets représentent la largeur de l'écran en pixels, les deux octets suivants sont la hauteur de l'écran. Après les octets de hauteur d'écran, les bits par octet de pixel doivent être présents dans le message. La valeur est généralement 8, 16 ou 32. Sur la plupart des systèmes modernes avec une plage de couleurs complète, les bits par octet de pixel ont la valeur 32 (0x20). Il indique au client qu'il peut demander la couleur complète pour chaque pixel du serveur. L'octet big endian est différent de zéro uniquement si les pixels sont dans l'ordre big endian. Si l'octet de couleur vrai est différent de zéro (vrai), les six octets suivants spécifient comment extraire les intensités de couleur rouge, verte et bleue de la valeur du pixel. Les six octets suivants sont les valeurs maximales autorisées pour la composante rouge, verte et bleue du pixel. Ceci est important en mode couleur 8 bits, où seuls quelques bits sont disponibles pour chaque composant de couleur. Les décalages rouge, vert et bleu déterminent les positions des bits pour chaque couleur. Les trois derniers octets sont du remplissage et doivent être ignorés par le client. Après le format de pixel, il y a un octet qui définit la longueur d'une chaîne pour le titre du bureau. Le titre du bureau est une chaîne codée ASCII dans un tableau d'octets de longueur arbitraire.



Protocole serveur-client Remote Framebuffer: échange de version, authentification et message d

Protocole serveur-client Remote Framebuffer: échange de version, authentification et message d'initialisation du serveur Tweet

Après le message d'initialisation du serveur, le service RFB doit lire les messages client à partir du socket et les décoder. Il existe 6 types de messages:

  • SetPixelFormat
  • SetEncodings
  • FramebufferUpdateRequest
  • L'évenement important
  • PointerEvent
  • ClientCutText

La documentation du protocole est assez exacte et explique chaque message. Pour chaque message, chaque octet est expliqué. Par exemple, message d'initialisation du serveur:

No d'octets Type La description
2 U16 largeur du tampon
2 U16 hauteur du tampon
16 PIXEL_FORMAT format-pixel-serveur
4 U32 nom-longueur
nom-longueur Réseau U8 chaîne de nom

Ici, PIXEL_FORMAT c'est:

No d'octets Type La description
un U8 bits par pixel
un U8 profondeur
un U8 drapeau-big-endian
un U8 drapeau de couleur vraie
2 U16 rouge-max
2 U16 green-max
2 U16 bleu-max
un U8 décalage vers le rouge
un U8 virage vert
un U8 décalage vers le bleu
3 rembourrage

U16 signifie un entier 16 bits non signé (deux octets), U32 est un entier 32 bits non signé, un tableau U8 est un tableau d'octets, etc.

qu'est-ce qu'un architecte de solutions certifié aws

Implémentation de protocole en Java

Une application serveur Java typique se compose d'un thread écoutant les connexions client et de plusieurs threads gérant les connexions client.

/* * Use TCP port 5902 (display :2) as an example to listen. */ int port = 5902; ServerSocket serverSocket; serverSocket = new ServerSocket(port); /* * Limit sessions to 100. This is lazy way, if * somebody really open 100 sessions, server socket * will stop listening and no new VNC viewers will be * able to connect. */ while (rfbClientList.size() <100) { /* * Wait and accept new client. */ Socket client = serverSocket.accept(); /* * Create new object for each client. */ RFBService rfbService = new RFBService(client); /* * Add it to list. */ rfbClientList.add(rfbService); /* * Handle new client session in separate thread. */ (new Thread(rfbService, 'RFBService' + rfbClientList.size())).start(); }

Ici, le port TCP 5902 a été choisi (affichage: 2) et la boucle while attend qu'un client se connecte. Méthode ServerSocket.accept () bloque et fait attendre le thread pour une nouvelle connexion client. Une fois le client connecté, un nouveau thread RFBService est créé qui gère les messages du protocole RFB reçus du client.

La classe RFBService implémente l'interface Runnable. Il est plein de méthodes pour lire les octets depuis le socket. Méthode courir() est important, qui est exécuté immédiatement lorsque le thread est lancé à la fin de la boucle:

@Override public void run() { try { /* * RFB server has to send protocol version string first. * And wait for VNC viewer to replay with * protocol version string. */ sendProtocolVersion(); String protocolVer = readProtocolVersion(); if (!protocolVer.startsWith('RFB')) { throw new IOException(); }

Ici méthode sendProtocolVersion () envoie une chaîne RFB au client (visionneuse VNC), puis lit la chaîne de version de protocole à partir du client. Le client doit répondre par quelque chose comme «RFB 003.008 n». Méthode readProtocolVersion () est bien sûr bloquante, comme toute méthode dont le nom commence par le mot read.

private String readProtocolVersion() throws IOException { byte[] buffer = readU8Array(12); return new String(buffer); }

La méthode readProtocolVersion () est simple: elle lit 12 octets à partir du socket et renvoie une valeur de chaîne. La fonction readU8Array (int) lit le nombre spécifié d'octets, dans ce cas 12 octets. S'il n'y a pas assez d'octets à lire sur le socket, il attend:

private byte[] readU8Array(int len) throws IOException { byte[] buffer = new byte[len]; int offset = 0, left = buffer.length; while (offset

Semblable à readU8Array (entier) , méthodes readU16int () et readU32int () existent qui lisent les octets de la socket et renvoient une valeur entière.

Après avoir envoyé la version du protocole et lu la réponse, le service RFB doit envoyer un message de sécurité:

/* * RFB server sends security type bytes that may request * a user to type password. * In this implementation, this is set to simples * possible option: no authentication at all. */ sendSecurityType();

Dans cette implémentation, le moyen le plus simple est choisi: ne nécessite aucun mot de passe du côté client VNC.

private void sendSecurityType() throws IOException { out.write(SECURITY_TYPE); out.flush(); }

où SECURITY_TYPE est un tableau d'octets:

private final byte[] SECURITY_TYPE = {0x00, 0x00, 0x00, 0x01};

Ce tableau d'octets de la version 3.3 du protocole RFB signifie que le visualiseur VNC n'a pas besoin d'envoyer de mot de passe.

Ensuite, ce que le service RFB doit obtenir du client est l'indicateur de bureau partagé. C’est un octet sur le socket.

/* * RFB server reads shared desktop flag. It's a single * byte that tells RFB server * should it support multiple VNC viewers connected at * same time or not. */ byte sharedDesktop = readSharedDesktop();

Une fois que l'indicateur de bureau partagé est lu à partir du socket, nous l'ignorons dans notre implémentation.

Le service RFB doit envoyer un message d'initialisation du serveur:

/* * RFB server sends ServerInit message that includes * screen resolution, * number of colors, depth, screen title, etc. */ screenWidth = JFrameMainWindow.jFrameMainWindow.getWidth(); screenHeight = JFrameMainWindow.jFrameMainWindow.getHeight(); String windowTitle = JFrameMainWindow.jFrameMainWindow.getTitle(); sendServerInit(screenWidth, screenHeight, windowTitle);

La classe JFrameMainWindow est JFrame, qui est ici à des fins de démonstration en tant que source de graphiques. Le message d'initialisation du serveur a une largeur et une hauteur d'écran obligatoires en pixels et un titre de bureau. Dans cet exemple, il s'agit du titre de JFrame obtenu par la méthode getTitle ().

Après le message d'initialisation du serveur, le thread de service RFB effectue une boucle en lisant à partir du socket six types de messages:

/* * Main loop where clients messages are read from socket. */ while (true) { /* * Mark first byte and read it. */ in.mark(1); int messageType = in.read(); if (messageType == -1) { break; } /* * Go one byte back. */ in.reset(); /* * Depending on message type, read complete message on socket. */ if (messageType == 0) { /* * Set Pixel Format */ readSetPixelFormat(); } else if (messageType == 2) { /* * Set Encodings */ readSetEncoding(); } else if (messageType == 3) { /* * Frame Buffer Update Request */ readFrameBufferUpdateRequest(); } else if (messageType == 4) { /* * Key Event */ readKeyEvent(); } else if (messageType == 5) { /* * Pointer Event */ readPointerEvent(); } else if (messageType == 6) { /* * Client Cut Text */ readClientCutText(); } else { err('Unknown message type. Received message type = ' + messageType); } }

Chaque méthode readSetPixelFormat () , readSetEncoding () , readFrameBufferUpdateRequest () , ... readClientCutText () bloque et déclenche une action.

Par exemple, readClientCutText () La méthode lit le texte qui est encodé dans le message lorsque l'utilisateur coupe le texte côté client, puis le visualiseur VNC envoie le texte via le protocole RFB au serveur. Le texte est ensuite placé côté serveur dans le Presse-papiers.

Client Messages

Les six messages doivent être pris en charge par le service RFB, au moins au niveau des octets: lorsque le client envoie un message, une longueur d'octet complète doit être lue. Cela est dû au fait que le protocole RFB est orienté octet et qu'il n'y a pas de frontière entre deux messages.

Le message le plus importé est la demande de mise à jour du tampon de trame. Le client peut demander une mise à jour complète ou une mise à jour incrémentielle de l'écran.

private void readFrameBufferUpdateRequest() throws IOException { int messageType = in.read(); int incremental = in.read(); if (messageType == 0x03) { int x_pos = readU16int(); int y_pos = readU16int(); int width = readU16int(); int height = readU16int(); screenWidth = width; screenHeight = height; if (incremental == 0x00) { incrementalFrameBufferUpdate = false; int x = JFrameMainWindow.jFrameMainWindow.getX(); int y = JFrameMainWindow.jFrameMainWindow.getY(); RobotScreen.robo.getScreenshot(x, y, width, height); sendFrameBufferUpdate(x_pos, y_pos, width, height, 0, RobotScreen.robo.getColorImageBuffer()); } else if (incremental == 0x01) { incrementalFrameBufferUpdate = true; } else { throw new IOException(); } } else { throw new IOException(); } }

Le premier octet du message de demande de tampon de trame est le type de message. La valeur est toujours 0x03. L'octet suivant est un indicateur incrémentiel, qui indique au serveur d'envoyer une image complète ou simplement une différence. En cas de demande de mise à jour complète, le service RFB prendra une capture d'écran de la fenêtre principale à l'aide de la classe RobotScreen et l'enverra au client.

S'il s'agit d'une demande incrémentielle, un indicateur incrementalFrameBufferUpdate sera défini sur true. Cet indicateur sera utilisé par les composants Swing pour vérifier s'ils doivent envoyer des parties de l'écran qui ont changé. Habituellement, JMenu, JMenuItem, JTextArea, etc. doivent effectuer une mise à jour incrémentielle de l'écran lorsque l'utilisateur déplace le pointeur de la souris, clique, envoie une frappe, etc.

La méthode sendFrameBufferUpdate (int, int, int, int, int []) vide le tampon d'image sur le socket.

public void sendFrameBufferUpdate(int x, int y, int width, int height, int encodingType, int[] screen) throws IOException { if (x + width > screenWidth || y + height > screenHeight) { err ('Invalid frame update size:'); err (' x = ' + x + ', y = ' + y); err (' width = ' + width + ', height = ' + height); return; } byte messageType = 0x00; byte padding = 0x00; out.write(messageType); out.write(padding); int numberOfRectangles = 1; writeU16int(numberOfRectangles); writeU16int(x); writeU16int(y); writeU16int(width); writeU16int(height); writeS32int(encodingType); for (int rgbValue : screen) { int red = (rgbValue & 0x000000FF); int green = (rgbValue & 0x0000FF00) >> 8; int blue = (rgbValue & 0x00FF0000) >> 16; if (bits_per_pixel == 8) { out.write((byte) colorMap.get8bitPixelValue(red, green, blue)); } else { out.write(red); out.write(green); out.write(blue); out.write(0); } } out.flush(); }

La méthode vérifie que les coordonnées (x, y) ne sortent pas de l'écran avec la largeur x la hauteur du tampon d'image. La valeur du type de message pour la mise à jour du tampon de trame est 0x00. La valeur de remplissage est généralement 0x00 et doit être ignorée par la visionneuse VNC. Le nombre de rectangles est une valeur de deux octets et définit le nombre de rectangles qui suivent dans le message.

dans quelle langue est écrit os x

Chaque rectangle a une coordonnée, une largeur et une hauteur en haut à gauche, un type de codage et des données de pixels. Certains formats d'encodage efficaces peuvent être utilisés, tels que zrle, hextile et tight. Cependant, pour garder les choses simples et faciles à comprendre, nous utiliserons le codage brut dans notre implémentation.

Le codage brut signifie que la couleur des pixels est transmise en tant que composant RVB. Si le client a défini le codage des pixels sur 32 bits, 4 octets sont transmis pour chaque pixel. Si le client utilise le mode couleur 8 bits, chaque pixel est transmis sous la forme d'un octet. Le code est affiché en boucle for. Notez que pour le mode 8 bits, la carte des couleurs est utilisée pour trouver la meilleure correspondance pour chaque pixel de la capture d'écran / du tampon d'image. Pour le mode pixel 32 bits, le tampon d'image contient un tableau d'entiers, chaque valeur a des composants RVB multiplexés.

Application de démonstration Swing

L'application de démonstration Swing contient un écouteur d'action qui se déclenche sendFrameBufferUpdate (int, int, int, int, int []) méthode. Habituellement, les éléments d'application, comme les composants Swing, doivent avoir des écouteurs et envoyer le changement d'écran au client. Par exemple, lorsque l'utilisateur tape quelque chose dans JTextArea, il doit être transmis au visualiseur VNC.

public void actionPerformed(ActionEvent arg0) { /* * Get dimensions and location of main JFrame window. */ int offsetX = JFrameMainWindow.jFrameMainWindow.getX(); int offsetY = JFrameMainWindow.jFrameMainWindow.getY(); int width = JFrameMainWindow.jFrameMainWindow.getWidth(); int height = JFrameMainWindow.jFrameMainWindow.getHeight(); /* * Do not update screen if main window dimension has changed. * Upon main window resize, another action listener will * take action. */ int screenWidth = RFBDemo.rfbClientList.get(0).screenWidth; int screenHeight = RFBDemo.rfbClientList.get(0).screenHeight; if (width != screenWidth || height != screenHeight) { return; } /* * Capture new screenshot into image buffer. */ RobotScreen.robo.getScreenshot(offsetX, offsetY, width, height); int[] delta = RobotScreen.robo.getDeltaImageBuffer(); if (delta == null) { offsetX = 0; offsetY = 0; Iterator it = RFBDemo.rfbClientList.iterator(); while (it.hasNext()) { RFBService rfbClient = it.next(); if (rfbClient.incrementalFrameBufferUpdate) { try { /* * Send complete window. */ rfbClient.sendFrameBufferUpdate( offsetX, offsetY, width, height, 0, RobotScreen.robo.getColorImageBuffer()); } catch (SocketException ex) { it.remove(); } catch (IOException ex) { ex.printStackTrace(); it.remove(); } rfbClient.incrementalFrameBufferUpdate = false; } } } else { offsetX = RobotScreen.robo.getDeltaX(); offsetY = RobotScreen.robo.getDeltaY(); width = RobotScreen.robo.getDeltaWidth(); height = RobotScreen.robo.getDeltaHeight(); Iterator it = RFBDemo.rfbClientList.iterator(); while (it.hasNext()) { RFBService rfbClient = it.next(); if (rfbClient.incrementalFrameBufferUpdate) { try { /* * Send only delta rectangle. */ rfbClient.sendFrameBufferUpdate( offsetX, offsetY, width, height, 0, delta); } catch (SocketException ex) { it.remove(); } catch (IOException ex) { ex.printStackTrace(); it.remove(); } rfbClient.incrementalFrameBufferUpdate = false; } } } }

Le code de cet écouteur d'action est assez simple: il prend une capture d'écran de la fenêtre principale JFrameMain en utilisant la classe RobotScreen, puis il est déterminé si une mise à jour partielle de l'écran est nécessaire. Variable diffUpdateOfScreen est utilisé comme indicateur pour une mise à jour partielle. Et enfin, un tampon d'image complet ou seules des lignes différentes sont transmises au client. Ce code considère également plus de clients connectés, c'est pourquoi l'itérateur est utilisé et la liste des clients est maintenue dans RFBDemo.rfbClientList membre.

L'écouteur d'action de mise à jour de Framebuffer peut être utilisé dans Timer qui peut être démarré par n'importe quel changement de JComponent:

/* * Define timer for frame buffer update with 400 ms delay and * no repeat. */ timerUpdateFrameBuffer = new Timer(400, new ActionListenerFrameBufferUpdate()); timerUpdateFrameBuffer.setRepeats(false);

Ce code est dans le constructeur de la classe JFrameMainWindow. Le minuteur est démarré dans la méthode doIncrementalFrameBufferUpdate ():

public void doIncrementalFrameBufferUpdate() { if (RFBDemo.rfbClientList.size() == 0) { return; } if (!timerUpdateFrameBuffer.isRunning()) { timerUpdateFrameBuffer.start(); } }

Les autres écouteurs d'action appellent généralement la méthode doIncrementalFrameBufferUpdate ():

public class DocumentListenerChange implements DocumentListener { @Override public void changedUpdate(DocumentEvent e) { JFrameMainWindow jFrameMainWindow = JFrameMainWindow.jFrameMainWindow; jFrameMainWindow.doIncrementalFrameBufferUpdate(); } // ... }

Cette méthode doit être simple et facile à suivre. Seule une référence à l'instance JFrameMainWindow est nécessaire et un seul appel de doIncrementalFrameBufferUpdate () méthode. La méthode vérifiera s'il y a des clients connectés, et s'il y en a, une minuterie timerUpdateFrameBuffer sera lancé. Une fois le chronomètre démarré, l'écouteur d'action prendra en fait une capture d'écran et sendFrameBufferUpdate () est exécuté.

La figure ci-dessus montre la relation de l'auditeur avec la procédure de mise à jour du tampon de trame. La plupart des écouteurs sont déclenchés lorsque l'utilisateur effectue une action: clique, sélectionne du texte, tape quelque chose dans la zone de texte, etc. Puis fonction membre doIncrementalFramebufferUpdate () est exécuté ce qui démarre le chronomètre timerUpdateFrameBuffer . La minuterie finira par appeler sendFrameBufferUpdate () dans la classe RFBService et cela provoquera une mise à jour de l'écran côté client (visionneuse VNC).

c corp contre s corp contre llc

Capturez l'écran, jouez les frappes et déplacez le pointeur de la souris sur l'écran

Java a une classe Robot intégrée qui permet au développeur d'écrire une application qui saisira des captures d'écran, enverra des clés, manipulera le pointeur de la souris, produira des clics, etc.

Pour saisir la zone de l'écran où la fenêtre JFrame est affichée, RobotScreen est utilisé. La méthode principale est getScreenshot (int, int, int, int) qui capture une région de l'écran. Les valeurs RVB de chaque pixel sont stockées dans un tableau int []:

public void getScreenshot(int x, int y, int width, int height) { Rectangle screenRect = new Rectangle(x, y, width, height); BufferedImage colorImage = robot.createScreenCapture(screenRect); previousImageBuffer = colorImageBuffer; colorImageBuffer = ((DataBufferInt) colorImage.getRaster().getDataBuffer()).getData(); if (previousImageBuffer == null || previousImageBuffer.length != colorImageBuffer.length) { previousImageBuffer = colorImageBuffer; } this.width = width; this.height = height; }

La méthode stocke les pixels dans le tableau colorImageBuffer. Pour obtenir des données de pixels, getColorImageBuffer () méthode peut être utilisée.

La méthode enregistre également le tampon d'image précédent. Il est possible de ne récupérer que les pixels qui ont été modifiés. Pour obtenir uniquement la différence de zone d'image, utilisez la méthode getDeltaImageBuffer () .

L'envoi de frappes au système est facile avec la classe Robot. Cependant, certains codes de clé spéciaux reçus des téléspectateurs VNC doivent d'abord être traduits correctement. La classe RobotKeyboard a une méthode sendKey (int, int) qui gère les touches spéciales et les touches alphanumériques:

public void sendKey(int keyCode, int state) { switch (keyCode) { case 0xff08: doType(VK_BACK_SPACE, state); break; case 0xff09: doType(VK_TAB, state); break; case 0xff0d: case 0xff8d: doType(VK_ENTER, state); break; case 0xff1b: doType(VK_ESCAPE, state); break; … case 0xffe1: case 0xffe2: doType(VK_SHIFT, state); break; case 0xffe3: case 0xffe4: doType(VK_CONTROL, state); break; case 0xffe9: case 0xffea: doType(VK_ALT, state); break; default: /* * Translation of a..z keys. */ if (keyCode >= 97 && keyCode <= 122) { /* * Turn lower-case a..z key codes into upper-case A..Z key codes. */ keyCode = keyCode - 32; } doType(keyCode, state); } }

L'état de l'argument détermine si la touche est enfoncée ou relâchée. Après traduction correcte du code clé en constante VT, méthode doType (int, int) passez la valeur de la clé à Robot et l'effet est le même que l'utilisateur local a appuyé sur la touche du clavier:

private void doType(int keyCode, int state) { if (state == 0) { robot.keyRelease(keyCode); } else { robot.keyPress(keyCode); } }

Similaire à RobotKeyboard est la classe RobotMouse qui gère les événements de pointeur et fait bouger le pointeur de la souris et cliquer.

public void mouseMove(int x, int y) { robot.mouseMove(x, y); }

Les trois classes RobotScreen, RobotMouse et RobotKeyboard allouent une nouvelle instance de Robot dans le constructeur:

this.robot = new Robot();

Nous n'avons qu'une seule instance de chacun, car il n'est pas nécessaire au niveau de l'application d'avoir plus d'une instance de la classe RobotScreen, RobotMouse ou RobotKeyboard.

public static void main(String[] args) { ... /* * Initialize static Robot objects for screen, keyboard and mouse. */ RobotScreen.robo = new RobotScreen(); RobotKeyboard.robo = new RobotKeyboard(); RobotMouse.robo = new RobotMouse(); ... }

Dans cette application de démonstration, ces instances sont créées dans principale() fonction.

Le résultat est une application basée sur Swing en Java qui agit comme un fournisseur de services RFB et permet aux visualiseurs VNC standard de s'y connecter:

Conclusion

Le protocole RFB est largement utilisé et accepté. Des implémentations client sous forme de visionneuses VNC existent pour presque toutes les plates-formes et tous les appareils. Le but principal est d'afficher les bureaux à distance, mais il peut également y avoir d'autres applications. Par exemple, vous pouvez créer des outils graphiques astucieux et y accéder à distance pour améliorer votre workflows à distance .

Cet article couvre les bases du protocole RFB, le format des messages, comment envoyer une partie de l'écran et comment gérer le clavier et la souris. Le code source complet avec l'application de démonstration Swing est disponible sur GitHub .

Terraform AWS Cloud: une gestion rationnelle de l'infrastructure

La Technologie

Terraform AWS Cloud: une gestion rationnelle de l'infrastructure
AI Investment Primer: A Practical Guide to Estising Artificial Intelligence Dealflow (Part II)

AI Investment Primer: A Practical Guide to Estising Artificial Intelligence Dealflow (Part II)

Processus Financiers

Articles Populaires
Comment créer un bouton SSO - Un didacticiel de connexion Flask
Comment créer un bouton SSO - Un didacticiel de connexion Flask
Invalidation du cache Rails au niveau du champ: une solution DSL
Invalidation du cache Rails au niveau du champ: une solution DSL
Tirer le meilleur parti des actions - Leçons d'un ancien analyste de recherche
Tirer le meilleur parti des actions - Leçons d'un ancien analyste de recherche
Programmation visuelle avec Node-RED: câbler l'Internet des objets en toute simplicité
Programmation visuelle avec Node-RED: câbler l'Internet des objets en toute simplicité
SaaS - Tactiques de tarification qui peuvent catapulter votre entreprise
SaaS - Tactiques de tarification qui peuvent catapulter votre entreprise
 
Programmation visuelle avec Node-RED: câbler l'Internet des objets en toute simplicité
Programmation visuelle avec Node-RED: câbler l'Internet des objets en toute simplicité
Introduction à Kotlin: programmation Android pour les humains
Introduction à Kotlin: programmation Android pour les humains
Pourquoi les devises des marchés émergents sont-elles volatiles?
Pourquoi les devises des marchés émergents sont-elles volatiles?
Comment créer une application multi-locataire: un didacticiel de mise en veille prolongée
Comment créer une application multi-locataire: un didacticiel de mise en veille prolongée
Guide de migration d'Oracle vers SQL Server et SQL Server vers Oracle
Guide de migration d'Oracle vers SQL Server et SQL Server vers Oracle
Articles Populaires
  • faire un bot pour discord
  • ouvrir le projet natif de réaction dans le studio Android
  • la mesure du retour sur investissement de la performance :
  • programmes qui utilisent c++
  • comment faire un bot de discussion discord
  • gestion des erreurs dans le nœud js
Catégories
  • Gestion De L'ingénierie
  • Gestion De Projet
  • Autre
  • Les Tendances
  • © 2022 | Tous Les Droits Sont Réservés

    portaldacalheta.pt