Olá, espero com esse post mostrar o funcionamento de um VNC VIEW básico em que um computador conecta à um outro computador remoto e então captura todas as telas que estão sendo visualizadas pelo computador host.

A idéia é bastante simples, basicamente transformar a imagem capturada pelo toolkit java, codificá-lá em um algoritmo (JPEG, GIF, PNG, etc...),transformá-lá em um array de bytes e enviar para rede. Do outro lado o computador que recebe as imagens só basta transformar o array de bytes em imagem e dá um repaint() na tela em um JFrame.

Essa ferramenta pode ser bem útil em aulas.

Apesar da simplicidade, vários outros aspectos podem ser levados em consideração tornando o projeto mais complexo como por exemplo capturar eventos do mouse e enviar para o computador que recebe as imagens como também criar agentes ativos que identifica computadores disponíveis para receber as imagens e então o computador host enviar para todos ao mesmo tempo em broadcast.

Imagem do funcionamento do programa


Palavras-chave: Java, VNC

Criando o projeto

  1. Vamos criar um JFrame bastante simples, cujo objetivo é mostrar a tela capturada no outro computador. A imagem a seguir demostra tal tela.



  2. Criando o núcleo da aplicação

  3. Vamos criar uma class Server. Usando um contexto que "server" será responsável por deixar a máquina disponível para receber imagens de um suposto "cliente" em que o "cliente" enviará as imagens para este "server". Um exemplo um computador A e um computador B, sendo o A o server então é nele que irá aparecer as imagens que estão sendo transmitida pelo computador B.

    Criando o Server


    Iremos criar a Class Server herdando de Thread, pois ela será responsável por abrir a conexão do socket de rede e esperar requisições. Quando uma requisição for enviada o método RUN da Thread é executado fazendo a operação de receber os Bytes enviado pelo "Client" e transformando em Image (BufferedImage).


    public class VirtualSchoolServer extends Thread {
    private Socket socket;
    private FmPrincipal fmChamado;

    public VirtualSchoolServer(Socket cliente) {
    setSocket(cliente);
    }

    No construtor enviamos um Socket responsável por abrir a conexão (Cliente). Esse FmPrincipal é o frame que exibirá a imagem. Ou seja, FmPrincipal e Server irão rodar juntos, quando o Server receber uma imagem enviará para o FmPrincipal e entao termina sua execução fechando a conexão e então abrimos uma nova Thread Server que espera indefinidamente até que o Client envi uma conexão.
    No método public void run() iremos transformar os bytes recebidos no socket e transformá-lo em BufferedImage. O código abaixo demostra como fazer isso.


  public void run(){

            try {

                System.out.println("Cliente conectado: " + socket.getInetAddress() " port " + socket.getLocalPort());

                InputStream is = socket.getInputStream();

                System.out.println("Download da imagem iniciado...");

                byte[] buffer = new byte[1024];

                int controle = 0;

                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                while ( (controle = is.read(buffer)) !=-) {

                    byte[] bufferReal = new byte[controle];

                    System.arraycopy(buffer, 0, bufferReal, 0, controle);

                    baos.write(bufferReal);

                }

                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

                BufferedImage bi = (BufferedImage)ImageIO.read(bais);

                if (bi != null) {

                    getFmChamado().setBi(bi);

                    System.out.println("Imagem recebida com sucesso... enviando para form");

                }

                else

                   System.out.println("Imagem recebida com falha... NULL")

 

            catch (Exception e) {

                    e.printStackTrace();

            }

            finally{

                    try {

                            socket.close();

                    catch (IOException e) {

                            e.printStackTrace();

                    }

            }


Criando a aplicação Cliente


Como explicado mais a cima, a aplicação cliente será responsável por enviar as imagens para o "server" para que este possa exibir as imagens recebidas. O código abaixo mostra como fazer isso.


public class VirtualSchoolClient {

   private static int i = 0;

   private static BufferedImage bi;

   private static Socket cliente;

   

   public static void main(String[] param) {

             while (true) {

                 try {

                    Toolkit ferramenta = Toolkit.getDefaultToolkit();

                    Rectangle tela = new Rectangle(ferramenta.getScreenSize());

                    Robot robot = new Robot();

                    bi = robot.createScreenCapture(tela);

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();

                    cliente = new Socket("localhost"8088);

                    cliente.getOutputStream().write(baos.toByteArray());



                    System.out.println("imagem enviada pelo cliente...");

                    ImageIO.write(bi, "JPG", cliente.getOutputStream());

                    cliente.getOutputStream().flush();

                    Thread.sleep(100);

                    catch (Exception e) {

                        e.printStackTrace();

                    }

                    finally{

                        try {

                                cliente.getOutputStream().close();

                                cliente.close();

                            catch (IOException e) {

                                    e.printStackTrace();

                            }

                    }

                }

   }



Criando a aplicação que dá um START no FmPrincipal e chama o "Server"





public class StartVirtualSchool {

    private static FmPrincipal jf = new FmPrincipal();

    @SuppressWarnings("static-access")

    public static void main(String[] args) {

        jf.setVisible(true);

        jf.capturaImage();

    }

}

Método capturaImage() FmPrincipal






    public void capturaImage(){

            try {

            ServerSocket ss = new ServerSocket(8088);

            while (true) {

                cliente = ss.accept();

                jlb_Status.setText("Conexao estabelecida");

                VirtualSchoolServer vs = new VirtualSchoolServer(cliente);

                vs.setFmChamado(this);

              vs.start();

                if (bi != null) {

                  double largura  = bi.getWidth();

                  largura -= largura * 0.2;

                  double altura = bi.getHeight();

                  Image imge = bi;

                  imge = imge.getScaledInstance(600400, Image.SCALE_FAST);

                  altura -= altura *0.2;

                  BufferedImage imt = new BufferedImage(600,400, BufferedImage.TYPE_INT_RGB);

                  imt.getGraphics().drawImage(imge, 00null);

                   ImageIcon icon = new ImageIcon(imt);

                  jImg.setSize(600400);

                  jImg.setIcon(icon);

                  System.out.println("Imagem diferente de NULL");

                   

                }else {

                    System.out.println("Imagem == NULL");

                }

                this.repaint();

            }

        catch (Exception e) {

            e.printStackTrace();

        }

    

    }