Countdown

Final Countdown

Faltam dias. Ou segundos.

domingo, 31 de janeiro de 2016

#28) Cursos Online

Bom dia!

Após um longo tempo sem postagens no blog, finalmente retorno com algumas ideias novas!

A primeira delas é a realização de cursos online com certificado, o que pode ser especialmente útil para demonstrar em um currículo o seu aprendizado da linguagem Java, por exemplo.

 Recentemente eu me matriculei em um curso da RLsystem sobre desenvolvimento Android. Apesar de ser um curso curto e bem básico, essa experiência foi ótima para consolidar os princípios de desenvolvimento de aplicativos usando o Eclipse. Abaixo deixo o link deste curso:

Curso Java & Android (gratuitos): http://www.rlsystem.com.br/curso-java-gratis/

Outro site famoso para programadores é o DevMedia. Seus cursos contam principalmente com recursos de tutoriais, além de serem mais extensos. Experimentei algumas aulas de PHP, das quais gostei muito, pelo caráter sempre prático. Também há lá cursos para a linguagem Java:

Cursos diversos DevMedia: http://www.devmedia.com.br/cursos/java

Eu poderia citar diversas outras plataformas de cursos online, como Coursera, Udemy, Veduca, etc. Mas pelo caráter prático que priorizamos neste blog, deixo essas duas indicações.

E você, leitor? Já fez algum curso online? Deixe abaixo no comentário.

Meu site https://ftuyama.com/

domingo, 30 de agosto de 2015

Python

Olá pessoal,

Sinto muito por ter abandonado temporariamente o blog. Comecei os meus estudos de Python, que eu passei a considerar a linguagem de programação mais poderosa.

#!/usr/bin/python
"""
Calculadora simples.

Para números em ponto flutuante utilize "." e não "," p.e.: 2.14
   
"""
__author__ = "Leonardo Gregianin"

import sys

class Valor:
    c = 0.000
    d = 0.000
    e = 0.000
    
    def valor1(self):
        try:
            self.c = input('Primeiro Valor: ')
            c = self.c
            return c
        except:
            print 'Inválido, digite um número! Se for float digite . e não ,'
        self.valor1()

    def valor2(self):
        try:
            self.d = input('Segundo Valor: ')
            d = self.d
            return d
        except:
            print 'Inválido, digite um número! Se for float digite . e não ,'
        self.valor2()

class Operador:
    
    def somar(self, c, d):
        self.e = c + d
        e = self.e
        return e

    def subtrair(self, c, d):
        self.e = c - d
        e = self.e
        return e
    
    def multiplicar(self, c, d):
        self.e = c * d
        e = self.e
        return e
    Earn free bitcoin
    def dividir(self, c, d):
        self.e = c / d
        e = self.e
        return e

class Resultado:
    
    def resultado(self, e, c, d):
        print('Resultado: %f')%(d)
   

if __name__ == "__main__":

    p1 = Valor()
    v1 = p1.valor1()
    v2 = p1.valor2()

    p2 = Operador()

    p3 = Resultado()
    
    operacao = raw_input('Operação: (+) (-) (*) (/) ou (s)air ]: ')
    
    while operacao:
        
        if operacao == 's':
            sys.exit()

        if operacao == '+':
            n1 = p2.somar(v1, v2)
            p3.resultado(None, None, n1)

        if operacao == '-':
            n1 = p2.subtrair(v1, v2)
            p3.resultado(None, None, n1)

        if operacao == '*':
            n1 = p2.multiplicar(v1, v2)
            p3.resultado(None, None, n1)

        if operacao == '/':
            n1 = p2.dividir(v1, v2)
            p3.resultado(None, None, n1)

        break

sábado, 27 de junho de 2015

Bizuca is online

Bizuca is Online!

Finalmente, concluímos o projeto de jogo em rede Web Bizuca. Abaixo temos alguns liks de documentação/ download do jogo:


Para visualizar a apresentação do jogo:


Para jogar, basta que alguém baixe o servidor .jar:

E depois se conectem a ele através do cliente:


Código:


Tempo de Projeto: 3 meses

Membros da Equipe: 2 membros

Diversão do Jogo: java.lang.StackOverflowError

#27) Developer Tools - Aplicações Web

Olá,

Hoje venho mostrar em meu último post referente ao curso de CES-22 a ferramenta Developer Tools para aplicações Web, a qual foi de extrema ajuda no desenvolvimento de nosso projeto:


Pressionando o Shortcut Ctrl + Shift + J em uma janela do navegador que esteja executando a sua aplicação, é possível visualizar diversas informações relevantes para o projeto:


  1. [Ícone Celular] - Permite visualizar a página Web em um formato de dispositivo móvel, sendo útil para prever o seu funcionamento em telas reduzidas.
  2. Elements : Permite visualizar o código através de seus blocos, permitindo alterar suas configurações.
  3. Network : Mostra a transferência de dados da aplicação e o tempo levado na transmissão. Excelente para detectar pontos críticos no projeto e procurar por otimizações. 
  4. Sources : Mostra os arquivos do projeto, desde imagens até os códigos .js empregados. Permite a sua alteração em tempo real, facilitando a edição da aplicação.
  5. Timeline : Permite ver os eventos em uma linha de tempo.
  6. Profile : Permite ver o uso de CPU (processamento) do usuário, também muito útil para otimizações do projeto.
  7. Resources : Visualização de banco de dados por trás das aplicações.
  8. Console : Exibe o console da aplicação.
Podemos ainda checar o FPS de um jogo, erros na compilação do projeto, dentre vários outros recursos.

segunda-feira, 15 de junho de 2015

#26) Design Patterns


Olá!

Hoje trataremos do assunto Design Patterns, que são princípios de desenvolvimento de software fáceis de serem compreendidos, modificados e expandidos. É uma solução para um problema que ocorre com frequência durante o projeto de Software, servindo como um modelo para a implementação de um programa.

Queremos evitar a implementação de uma classe God centralizada que realiza todas as tarefas do nosso programa: https://en.wikipedia.org/wiki/God_object
Implementação que vai contra os princípios de Design Patterns.

O que diferencia um programador amador de um profissional? Um amador gera códigos compiláveis sem se preocupar com a estrutura de seu código, enquanto um profissional emprega os princípios de Design Patterns para desenvolver um código muito eficiente do ponto de vista de projeto, apto a sofrer atualizações e modificações ao longo do tempo.

O site PrinciWeb traz uma abordagem bem lúdica sobre o tema:

Design patterns (padrões de projeto) surgiram com a motivação de ajudar a solucionar problemas que ocorrem frequentemente, e, se usados com bom senso, podem se tornar ferramentas poderosas para qualquer desenvolvedor de software, uma vez que já foram testadas, utilizadas e aprimoradas a partir da experiência e conhecimento de outros programadores.
Preparamos um post explicando o que são design patterns e seus princípios comuns, baseado no livro “Professional ASP.NET Design Patterns” de Scott Millett.
Design Patterns - Vida de Programador
Tirinha retirada do site Vida de Programador, o qual publica tirinhas diárias com histórias engraçadas e verídicas sobre o dia-a-dia de um programador.

Explicando Design Patterns

Design patterns (Padrões de projeto) são soluções de templates abstratas de alto nível. Pense nelas como um “blueprint” (desenho técnico ou documentação de uma arquitetura, etc.) para soluções e não como uma solução por si própria. Você não achará um framework que você poderá simplesmente aplicar para a sua aplicação; ao invés disso, você chegará ao design patterns através da refatoração do seu código e generalização do seu problema.
Design patterns não são somente aplicados em desenvolvimento de software; design patterns podem ser encontrados em diversas áreas da vida, da engenharia até da arquitetura. Em fato, foi o arquiteto Christopher Alexander que introduziu a ideia de patterns em 1970 para construir um vocabulário comum para discussões sobre design. Ele escreveu:
Cada pattern descreve um problema que ocorre várias vezes ao nosso redor e com isso, descrevem a solução para o problema de uma maneira que você pode usar essa solução diversas vezes sem ter que fazer a mesma coisa duas ou mais vezes.

Vamos então abordar os principais conceitos de Design Patterns:

Princípios de Design

Alguns dos princípios mais conhecidos de Desing Patterns voltados para o desenvolvimento de software nível empresarial são citados abaixo:
  1. DRY (Don't Repeat Yourself) : Não repetir o código, utilizar abstrações para coisas comuns.
  2. KISS (Keep It Simple Stupid) : Tentar manter o código o mais simples possível.
  3. TDA (Tell, Don't Ask) : Você deve dizer ao objeto qual tarefa ele deve realizar, sem se preocupar com o estado dele. Ou seja, promove o encapsulamento do código e torna as classes mais independentes.
  4. YAGNI (You Ain't Gonna Need It) : Adicionar somente as funcionalidades necessárias para o funcionamento da aplicação.
  5. TDD (Test Driven Development) : Método de desenvolvimento baseado em testes: O desenvolvimento da aplicação é inteiramente voltada para o êxito dos testes criados.
  6. SoC (Separation of Concerns) : Separa o código em funcionalidades distintas, promovendo o seu encapsulamento e distribuindo responsabilidades para cada classe.
Podemos ainda citar alguns princípios por trás dos princípios:
  1. Encapsular : Encapsular todo o código passível de alteração no futuro.
  2. Programar para a Interface, não para a implementação.
  3. Não implementar responsabilidades que devem ser delegadas às classes.
  4. Preferir a composição invés da herança, devido à sua maior flexibilidade.

Princípios de Design Orientado a Objetos

Vamos agora abordar SOLID, 5 princípios básicos de design orientado a objetos. Indico fortemente a referência http://www.itexto.net/devkico/?p=1105 para obter exemplos práticos da aplicação destes princípios.

  • Single Responsibility (SRO): Cada classe deve ter uma única responsabilidade. Isso distribui as tarefas evitando a sobrecarga em uma única classe, reduzindo o código fonte e eliminando problemas de bugs.
  • Open Closed Design (OCP): As classes devem ser abertas para extensões e fechadas para modificações.
  • Liskov Substitution : As subclasses devem sempre aumentar as funcionalidades das superclasses, nunca reduzi-las.
  • Interface Segregation (ISP) : Evitar a criação de classes poderosas. Se uma classe tem muitas funcionalidades, empregar interfaces para diferentes responsabilidades, dividindo as tarefas.
  • Dependency Injection (DIP) : Um módulo de nível superior não deve depender de um módulo de nível inferior. Ambos devem depender apenas de abstrações.

Padrões GoF (Group of Four)

Da referência http://pt.wikipedia.org/wiki/Padr%C3%A3o_de_projeto_de_software, temos uma pequena lista de padrões GoF, bem como a sua classificação:
Os padrões "GoF" são organizados em 3 famílias :
  • Padrões de criação : relacionados à criação de objetos
  • Padrões estruturais : tratam das associações entre classes e objetos.
  • Padrões comportamentais : tratam das interações e divisões de responsabilidades entre as classes ou objetos.

Padrões de criação

  • Abstract Factory : Através dele uma classe simplesmente cria o objeto que você gostaria de usar.
  • Builder : Encapsular a construção de um produto, construindo-o por etapas.
  • Factory Method : As subclasses decidem quais classes concretas serão criadas.
  • Prototype : Permite criar novas instâncias clonando instâncias já existentes.
  • Singleton : Uma classe que só possui uma única instância. Já mostrei esse conceito no blog, no post "objeto global".

Padrões estruturais

  • Adapter : Envelopa o objeto e fornece a ele uma interface diferente.
  • Bridge : Cria uma ponte para variar implementações e abstrações.
  • Composite : O cliente trata as coleções de objetos e objetos individuais de maneira uniforme.
  • Decorator : Envelopa objeto para fornecer novos comportamentos.
  • Façade (ou Facade) : Simplifica a interface de um conjunto de classes.
  • Flyweight : Uma instância de uma classe pode fornecer várias instâncias virtuais (como o casa da bala virtual, no jogo Bizuca).
  • Proxy : Envelopa o objeto para controlar o acesso a ele.

Padrões comportamentais

  • Chain of Responsibility : Permite a mais de um objeto a oportunidade de processar uma solicitação.
  • Command : Encapsula uma solicitação como um objeto.
  • Interpreter : Constrói um intérprete para uma linguagem (como o uso de protocolos de comunicação em uma aplicação Cliente - Servidor, que precisa codificar todas as informações do projeto em uma String, por exemplo).
  • Iterator : Permite acessar sequencialmente uma coleção de objetos sem expor a sua implementação (Como, por exemplo, quando percorremos um ArrayList).
  • Mediator : Centraliza operações complexas de comunicação e controle de entre objetos relacionados (classe Comunicação entre cliente e servidor, por exemplo).
  • Memento : Permite restaurar o objeto a um de seus estados prévios (desfazer). Um exemplo já mostrado no blog é a funcionalidade Canvas do HTML, que permite salvar seu estado (ctx.save()) e restaurá-lo posteriormente (ctx.restore()), desfazendo translações, rotações, etc.
  • Observer : Permite notificar outros objetos sobre mudanças de estado.
  • State : Encapsula comportamentos em baseados em Estados e usa delegações para alternar comportamentos. (Também usado no projeto Web Bizuca, estados para recibo de mensagens).
  • Strategy : Encapsula famílias de algoritmos permitindo à classe cliente instanciar estes algoritmos  sem necessitar reconhecer a sua implementação atual.
  • Template Method : As subclasses decidem como implementar os passos de um algoritmo.
  • Visitor : Permite acrescentar novos recursos a um composto de objetos.
Um padrão "GoF" também é classificado segundo o seu escopo em 2 outros grupos :

Bem, com isso concluímos o post de hoje, que dá um panorama generalizado do que são Design Patterns. Caso o leitor se interessar pelo conteúdo, pode aprofundar o seu estudo com exemplos práticos nas referências abaixo:

Referências:

(Exemplos práticos dos princípios SOLID):

(Fala dos princípios básicos de Design Patterns):
http://www.princiweb.com.br/blog/programacao/design-patterns/o-que-sao-design-patterns.html

(Padrões GoF):
http://pt.wikipedia.org/wiki/Padr%C3%A3o_de_projeto_de_software
http://www.devmedia.com.br/design-patterns-descricoes-dos-padroes-gof-parte-2/16781

(Exemplos de GoF (em PHP)):
http://br.phptherightway.com/pages/Design-Patterns.html

(Considere essa referência como uma enciclopédia para consulta):
https://lealcy.wordpress.com/gambi-design-patterns/

sábado, 6 de junho de 2015

#25) Animações em HTML - Canvas

Bom dia,

Hoje venho apresentar rapidamente uma ferramenta que descobri para desenvolver animações em HTML, o Canvas, muito semelhante à biblioteca Graphics que utilizamos na linguagem Java.

Para utilizá-la, basta simplesmente invocá-la na estrutura .html de sua página:

<canvas id="myCanvas" width="200" height="100" ></canvas>

Depois, no código Javascript, criamos uma variável que faça referência ao Canvas criado, sendo que já se torna possível criar desenhos básicos com ele, como na ferramenta Graphics:

Desenhando um retângulo no Canvas.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,150,75);
Torna-se possível agora desenhar linhas, textos, circunferências, imagens, etc, permitindo-nos construir animações simples com auxílio da linguagem javascript. Para obter mais informações, consulte uma das referências indicadas.

Podemos assim, adicionar vários elementos Javascript ao nosso projeto, para a leitura de inputs do usuário (fazer o bloco se mover, por exemplo), realizar conexão de dados (como no projeto de jogo Web Bizuca Online) ou mesmo animações paralelas.




Como eu odeio explicações incompletas, resolvi adaptar o código da referência do site do mozilla (animação planetária) e adicionar inputs a essa animação, permitindo ao usuário controlar seu próprio planeta :)

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="input.js"></script>
        <title>Animação</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body onload="init();" onkeydown="press(event);" onkeyup="release(event);">
        <canvas id="myCanvas" width="600" height="600" ></canvas>
        <script type="text/javascript">
            var x = 300, y = 300;
            var sun = new Image();
            var moon = new Image();
            var earth = new Image();
            function init() {
                sun.src =
'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
                moon.src =
'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
                earth.src =
'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
                window.requestAnimationFrame(draw);
            }

            function draw() {
                var ctx = document.getElementById('myCanvas').getContext('2d');

                ctx.globalCompositeOperation = 'destination-over';
                ctx.clearRect(0, 0, 500, 500); // clear canvas

                ctx.fillStyle = 'rgba(0,0,0,0.4)';
                ctx.strokeStyle = 'rgba(0,153,255,0.4)';
                ctx.save();
                ctx.translate(150, 150);

                // Earth
                var time = new Date();
                ctx.rotate(((2 * Math.PI) / 60) * time.getSeconds() + ((2 *
                        Math.PI) / 60000) * time.getMilliseconds());
                ctx.translate(105, 0);
                ctx.fillRect(0, -12, 50, 24); // Shadow
                ctx.drawImage(earth, -12, -12);

                // Moon
                ctx.save();
                ctx.rotate(((2 * Math.PI) / 6) * time.getSeconds() + ((2 *
                        Math.PI) / 6000) * time.getMilliseconds());
                ctx.translate(0, 28.5);
                ctx.drawImage(moon, -3.5, -3.5);
                ctx.restore();

                ctx.restore();

                ctx.beginPath();
                ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit
                ctx.stroke();


  // Earth
                ctx.drawImage(earth, x, y);

                ctx.drawImage(sun, 0, 0, 300, 300);

                processInput();
                window.requestAnimationFrame(draw);
            }

            function processInput()
            {
                this.idle = true;

                if (window.inLeft()) {
                    x--;
                    this.idle = false;
                }
                if (window.inRight()) {
                    x++;
                    this.idle = false;
                }
                if (window.inUp()) {
                    y--;
                    this.idle = false;
                }
                if (window.inDown()) {
                    y++;
                    this.idle = false;
                }
            }
            init();
        </script>
    </body>
</html>
Somente para ilustrar o resultado de um curto código usando Canvas e para dar ao leitor um pontapé inicial, temos o pequeno exemplo compilável abaixo:

<html>
<head></head>
<body onload="init();">
 <canvas id="myCanvas" width="200" height="100" ></canvas>
 <script type="text/javascript">
 var c = document.getElementById("myCanvas");
 var ctx = c.getContext("2d");
 function init()
 {
  ctx.fillStyle = "#FF0000";
  ctx.fillRect(0,0,150,75);
 }
 </script>
</body>
</html>

Não esqueça de incluir o arquivo input.js no mesmo diretório deste arquivo .html:

var KEY = {
  D: 68,
  W: 87,
  A: 65,
  S:83,
  RIGHT:39,
  UP:38,
  LEFT:37,
  DOWN:40,
  Q:81
};

var input = {
  right: false,
  up: false,
  left: false,
  down: false,
  quit: false
};

window.inLeft = function(){
    return input.left;
};
window.inRight = function(){
    return input.right;
};
window.inDown = function(){
    return input.down;
};
window.inUp = function(){
    return input.up;
};

function press(evt) {
  var code = evt.keyCode;
  switch(code) {
    case KEY.RIGHT:
    case KEY.D: input.right = true; break;

    case KEY.UP:
    case KEY.W: input.up = true; break;

    case KEY.LEFT:
    case KEY.A: input.left = true; break;
 
    case KEY.DOWN:
    case KEY.S: input.down = true; break;
 
    case KEY.Q: input.quit = true; break;
  }
}

function release(evt) {
  var code = evt.keyCode;
  switch(code) {
    case KEY.RIGHT:
    case KEY.D: input.right = false; break;

    case KEY.UP:
    case KEY.W: input.up = false; break;

    case KEY.LEFT:
    case KEY.A: input.left = false; break;

    case KEY.DOWN:
    case KEY.S: input.down = false; break;

    case KEY.Q: break;

    default: trace('unrecognized key code: ' +code); break;
  }
}
Quando criamos uma função do tipo window.função = function () {...}, estamos na verdade criando uma função global que pode ser chamada de outros arquivos .js. Não existem variáveis globais em javascript, porém o conceito de funções globais pode ser utilizado. Outro meio de codificar é usar um método main() no arquivo .html, centralizando as operações de vários arquivos .js do projeto.

Bem, o interesse aqui não é aprofundar muito na nova ferramenta, mas apenas anunciar a sua descoberta, que será utilizada para a construção do nosso projeto.

Referências:

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/A_basic_ray-caster

segunda-feira, 1 de junho de 2015

#24) Aplicações Web

Boa noite,

Hoje o tópico será sobre Aplicações Web.

1. Introdução (Segurança)

Vamos falar hoje sobre um dos campos mais hostis e inóspitos que existe no ramo da programação: O ambiente Web. Um ambiente fértil para novas aplicações e que representa cada vez mais o futuro do desenvolvimento de softwares, mas ao mesmo tempo traz uma série de dificuldades.

Adicionei um novo Gadget ao meu blog para demonstrar como a Web pode ser um ambiente terrível e perigoso. O Gadget mostra em tempo real o fluxo de ataques DDOS realizados ao redor do mundo. Lembrando a definição de ataque DDOS:

"A Distributed Denial of Service (DDoS) attack is an attempt to make an online service unavailable by overwhelming it with traffic from multiple sources. They target a wide variety of important resources, from banks to news websites, and present a major challenge to making sure people can publish and access important information".



Se você, leitor, se interessou pelo tema, aconselho que aprofunde um pouco mais sua visão com algum dos links da referência deste post. Sei que minha abordagem apreensiva quanto à segurança é um pouco inusitada, mas é ela que explica fatos como, por exemplo:
  •  A implementação de Applets em Java ser tão difícil e pouco estimulada devido aos perigos que uma máquina virtual (proveniente da execução do aplicativo) pode ocasionar ao seu utilizador.
  • Não há possibilidade de se utilizar diretamente serviços Sockets (explicaremos neste post) e envio de Packets empregando Javascript, o que poderia ser um desastre de segurança.
  • A enorme dificuldade de se hospedar arquivos online de forma gratuita, principalmente de aplicações que não sejam em HTML (um arquivo executável .jar, por exemplo), devido às aplicações maliciosas que viriam daí.
E estes são alguns poucos itens que enuncio aqui, dificuldades sérias para o nosso projeto Web que se originam fundamentalmente de problemas de segurança em rede.


2. Predefinição

A linguagem Java conta com uma boa API de Sockets pelo pacote java.net, que será o mais utilizado aqui neste post. Antes, vamos tomar algumas definições básicas:

Glossário

  1. Socket (soquete de rede) é o ponto final do fluxo de informação entre 2 aplicativos através de uma rede.
  2. Packet (pacote) é uma estrutura unitária de transmissão de dados em uma rede de comunicação.
  3. Protocolo (TCP - Transmission Control Protocol) é uma convenção que controla e possibilita uma conexão/ comunicação/ transferência de dados entre dois sistemas computacionais.
  4. IP (IP - Internet Protocol) pode ser definido como um protocolo de comunicação em conjunto com o TCP (TCP/IP).
  5. Endereço IP é uma identificação de um dispositivo em uma rede local ou pública. Cada endereço de domínio é convertido em um endereço IP pelo DNS (resolução de nomes).
  6. Porta, assim como o IP existe para identificar uma máquina, a porta é solução para identificar as diversas aplicações de uma máquina. É um número de 2 bytes (varia de 0 a  65535)
  7. DNS é um sistema de gerenciamento de nomes hierárquicos distribuídos para computadores, serviços ou qualquer recurso conectado à internet ou a uma rede privada.
  8. IPV4 é um cabeçalho que contém as informações a serem transmitidas segundo uma certa lógica. Seu endereçamento possui 32 bits.
  9. UDP é um protocolo simples da camada de transporte. Permite que a aplicação escreva um datagrama encapsulado num pacote IPV4 ou IPV6 e então envia ao destino, mas não garante a chegada ao destino ou não.
  10. Datagrama é uma unidade de transferência básica associada a uma rede de comutação de pacotes em que a entrega, hora de chegada e ordem não são garantidas.
  11. Domínio é um nome que serve para localizar um conjunto de computadores na internet.
  12. Servidor é uma aplicação central que espera a conexão de Clientes para a sua execução.

Blocos de Endereços Reservados
CIDR Bloco de EndereçosDescriçãoReferência
0.0.0.0/8Rede corrente (só funciona como endereço de origem)RFC 1700
10.0.0.0/8Rede PrivadaRFC 1918
14.0.0.0/8Rede PúblicaRFC 1700
39.0.0.0/8ReservadoRFC 1797
127.0.0.0/8LocalhostRFC 3330
128.0.0.0/16Reservado (IANA)RFC 3330
169.254.0.0/16ZeroconfRFC 3927
172.16.0.0/12Rede privadaRFC 1918
191.255.0.0/16Reservado (IANA)RFC 3330
192.0.2.0/24DocumentaçãoRFC 3330
192.88.99.0/24IPv6 para IPv4RFC 3068
192.168.0.0/16Rede PrivadaRFC 1918
198.18.0.0/15Teste de benchmark de redesRFC 2544
223.255.255.0/24ReservadoRFC 3330
224.0.0.0/4Multicasts (antiga rede Classe D)RFC 3171
240.0.0.0/4Reservado (antiga rede Classe E)RFC 1700
255.255.255.255Broadcast

3. Sockets (Java)

Vamos esquentar um pouco com um pequeno exemplo de aplicação Cliente - Servidor em Java, em que cliente e servidor trocam uma simples mensagem entre si:

A aplicação Servidor disponibiliza uma determinada porta e espera a conexão do Cliente, para depois realizar a leitura dos dados enviados por ele, para depois enviar uma curta mensagem. Note que há a criação de um Socket de conexão:

ServerSocket servidor = new ServerSocket( porta );

Server.java
package sockets;

import java.io.*;
import java.net.*;
import java.util.*;

public class Server 
{
    static String Mensagem = "Hi", N;
    static String IPclient, IPserver, porta;
    static Socket cliente;
    public static void main(String[] args) throws UnknownHostException, IOException 
    {
        // Campo para exibir IPserver e porta
        IPserver = InetAddress.getLocalHost().getHostAddress();
        porta = "7777";
        
        ServerSocket servidor = new ServerSocket(Integer.parseInt(porta));
        
        // Detecção de nova requisição do cliente.
        while (cliente == null) 
        {
            cliente = servidor.accept();
            IPclient = cliente.getLocalAddress().getHostAddress();
        }
            // Leitura do valor de N
            Scanner s = new Scanner(cliente.getInputStream());
            N = s.nextLine();
            System.out.println(N);

            // Escreve a mensagem codificada.
            PrintStream saida = new PrintStream(cliente.getOutputStream());
            saida.println(Mensagem);
            
            
            while(!cliente.isClosed())
        
        saida.close();        
        cliente.close();
    }

}

Para a aplicação Cliente, temos a conexão ao servidor e depois o subsequente envio envio de uma mensagem, para depois aguardar a mensagem enviada pelo cliente. Note que a conexão Socket é realizada no formato (IP, porta), conforme a sua definição:

 Socket cliente = new Socket( IP, porta );

Client.java
package sockets;

import java.io.*;
import java.net.*;
import java.util.*;

public class Client 
{
    static String Mensagem, N = "10";
    static String IPclient, IPserver, porta;
    static Socket cliente;
    public static void main(String[] args) throws UnknownHostException, IOException 
    {
        // Campo para digitar IPserver & Porta & exibir IPcliente
        IPserver = "192.168.197.1";
        porta = "7777";
        IPclient = InetAddress.getLocalHost().getHostAddress();
        
        // Conexão ao servidor
        cliente = new Socket(IPserver, Integer.parseInt(porta));
        
            // Cliente envia o valor de "n"
            PrintStream saida = new PrintStream(cliente.getOutputStream());
            saida.println(N);
            
            // Realiza a leitura da mensagem
            Scanner s = new Scanner(cliente.getInputStream());
            Mensagem = s.nextLine();
            System.out.println(Mensagem);

        saida.close();
        cliente.close();
    }
}

Como o leitor pode observar, o uso da aplicação é bem direto, sendo que o grande desafio é sincronizar o envio das mensagens usando Threads, identificar usuários que se conectam ao servidor e distribuir portas de conexão a eles, permitir diversos clientes simultâneos, etc.

Estes desafios podem ser resolvidos usando os conceitos que viemos desenvolvendo até agora no blog, de modo que deixaremos isso ao encargo do leitor.

4. WebSockets (Javascript)


Note que para usar WebSockets, será necessário criar um arquivo HTML estático como estrutura para o código dinâmico do Javascript. Fundamentalmente, Javascript não permite a utilização de Sockets diretamente como ocorre na linguagem Java, por motivos de segurança. 

No entanto, WebSockets surge como uma alternativa moderna para contornar esse problema, usando funções encapsuladas de forma a restringir o uso de Sockets e a sua implementação.

Abaixo temos um exemplo de aplicação de WebSockets:

<!DOCTYPE HTML>
<html>

   <head>
 
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("WebSocket is supported by your Browser!");
               // Let us open a web socket
               var ws = new WebSocket("ws://localhost:9998/echo");
    
               ws.onopen = function()
               {
                  // Web Socket is connected, send data using send()
                  ws.send("Message to send");
                  alert("Message is sent...");
               };
    
               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  alert("Message is received...");
               };
    
               ws.onclose = function()
               { 
                  // websocket is closed.
                  alert("Connection is closed..."); 
               };
    
            }
            else
    
            {
               // The browser doesn't support WebSocket
               alert("WebSocket NOT supported by your Browser!");
            }
         }
      </script>
  
   </head>
 
   <body>
      <div id="sse">
         <a href="javascript:WebSocketTest()">Run WebSocket</a>
      </div>
   </body>
 
</html>

Por outro lado, devemos empregar um Servidor, como por exemplo o Glassfish, para a criação de um terminal Servidor, com um endereço do tipo:

"ws://localhost:8080/Bizuca/server"

package Servidor;

import java.io.IOException;
import java.util.ArrayList;
 
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/server") 
public class Servidor 
{   
    ArrayList<Player> Players = new ArrayList<>();
    public static int i = 0;
    public static String Msg = "";
    
    @OnOpen
    public void onOpen(Session session)
    {
        Players.add(new Player("null",session.getId()));
        try {
            session.getBasicRemote().sendText("Conexão estabelecida. Nº"+(i++));
        } catch (IOException ex) { }
    }
    
    @OnMessage
    public void onMessage(String message, Session session)
    {
        Msg = message;
            message+=": Sender : ("+session.getId()+")";
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException ex) { }
    }
 
    @OnClose
    public void onClose(Session session){
        for(Player P: Players)
            if (P.Id.equals(session.getId()))
                Players.remove(P);
    }
}

É possível inclusive colocar essa aplicação online com uso de servidor Glassfish, empregando por exemplo o serviço Layershift (versão trial de 14 dias), com permissão ao uso de banco de dados online e execução da sua aplicação em um ambiente online.

Ambiente Layershift para Upload de projetos.


Porém sempre existem alternativas, como o emprego da API Sockets.io, que permite o uso de Sockets de maneira simplificada, ou da API jsocket, desenvolvida no MIT, que emprega arquivos Flash para burlar o sistema de segurança agressivo de Javascript.

5. Programando em baixo nível

Somente para ilustrar um pouco mais os conceitos abordados neste tópico, temos o seguinte exemplo de aplicação de Datagramas (a unidade básica de transferência de dados) em um chat, permitindo vislumbrar em baixo nível como é realizada a troca de informações na Web:

A classe Conexão realiza a conexão dos usuários e também se encarrega da interpretação e da troca de mensagens, convertendo Datagrams em mensagens e vice-e-versa:

package online;
import java.io.IOException;
import java.util.logging.*;
import java.net.*;
import java.util.*;

public class Conexao extends Observable 
{
    private String ip, mensagem;
    private int porta;

    public void SetConexao(String ip, int porta) {
        this.ip = ip; this.porta = porta;
        new Thread(new Recebe()).start();
    }
    public String getIP () {
        try {
            return ""+InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException ex) {
            Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
    public String getMensagem() { return mensagem; }
    public String getIp() { return ip; }
    public int getPorta() {  return porta;  }
    public void envia(String texto) {  new Thread(new Envia(texto)).start();  }

    public void notifica(String mensagem) {
        this.mensagem = mensagem;
        setChanged();
        notifyObservers();
    }

    class Recebe implements Runnable 
    {
        byte[] dadosReceber = new byte[255];
        boolean erro = false;
        DatagramSocket socket = null;

        @Override
        public void run() {
            while (true) {
                try {
                    socket = new DatagramSocket(getPorta());
                } catch (SocketException ex) {
                    Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
                }
                erro = false;
                while (!erro) {
                    DatagramPacket pacoteRecebido = new DatagramPacket(dadosReceber, dadosReceber.length);
                    try {
                        socket.receive(pacoteRecebido);
                        byte[] b = pacoteRecebido.getData();
                        String s = "";
                        for (int i = 0; i < b.length; i++)
                            if (b[i] != 0)
                                s += (char) b[i];
                        String nome = pacoteRecebido.getAddress().toString() + " disse:";
                        notifica(nome + s);
                    } catch (Exception e) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        erro = true;
                        continue;
                    }
                }
            }
        }
    }

    class Envia implements Runnable 
    {
        String texto;
        public Envia(String texto) {
            this.texto = texto;
        }
        @Override
        public void run() {
            byte[] dados = texto.getBytes();

            try {
                DatagramSocket clientSocket = new DatagramSocket();
                InetAddress addr = InetAddress.getByName(getIp());
                DatagramPacket pacote = new DatagramPacket(dados, dados.length, addr, getPorta());
                clientSocket.send(pacote);
                clientSocket.close();
            } catch (SocketException ex) {
                Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
            } catch (UnknownHostException ex) {
                Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

Interface gráfica, responsável por capturar as mensagens e exibi-las, além de gerenciar as ferramentas usadas pelo usuário:

package online;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Observable;
import java.util.Observer;

public class GUI extends JFrame implements Observer 
{
    int xMouse, yMouse;
    private Conexao conex;
    private JTextField textoIP, textoPorta;
    private JTextArea chatjTextArea, mensagemjTextArea;     
    private JButton enviarjButton, connect;
    private JScrollPane jScrollPane1, jScrollPane2; 
    private JLabel credito, IP, porta, meuIP;
    
    public GUI (Conexao conexao)
    {
        conex = conexao;
        conex.addObserver(this);
        initComponents();
        initEvents();
        setBounds(250,150,600,550);
        escreve("Chat iniciado com " + conex.getIp() + ":" + conex.getPorta());
        meuIP.setText("Meu IP: "+conex.getIP());
    }
    private void initComponents()
    {
        setTitle("Xhat");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(new Color(0, 0, 0));
        setLocationRelativeTo(null); setLayout(null); setVisible(true);
        
        IP = new JLabel("IP:"); IP.setForeground(Color.white); IP.setBounds(50,50,100,20); add(IP);
        porta = new JLabel("Porta:"); porta.setForeground(Color.white); porta.setBounds(200,50,100,20); add(porta);
        meuIP = new JLabel(); meuIP.setForeground(Color.white); meuIP.setBounds(200,20,150,20); add(meuIP);
        
        textoIP = new JTextField("192.168.0."); textoIP.setBounds(70,50,100,25);
        textoIP.setBackground(Color.black); textoIP.setForeground(Color.white); add(textoIP);
        textoPorta = new JTextField("5000"); textoPorta.setBounds(250,50,100,25);
        textoPorta.setBackground(Color.black); textoPorta.setForeground(Color.white); add(textoPorta);
        
        chatjTextArea = new JTextArea();  chatjTextArea.setEditable(false);
        chatjTextArea.setForeground(Color.white); chatjTextArea.setBackground(Color.black);
        jScrollPane1 = new JScrollPane(); jScrollPane1.setBounds(50,100,450,300); add(jScrollPane1);
        jScrollPane1.setViewportView(chatjTextArea);
        
        mensagemjTextArea = new JTextArea(); mensagemjTextArea.requestFocusInWindow();
        mensagemjTextArea.setForeground(Color.white); mensagemjTextArea.setBackground(Color.black);
        jScrollPane2 = new JScrollPane(); jScrollPane2.setBounds(50,400,350,50); add(jScrollPane2);
        jScrollPane2.setViewportView(mensagemjTextArea);
        
        connect = new JButton("Conectar"); 
        connect.setBackground(Color.black); connect.setForeground(Color.white);
        connect.setBounds(400,50,100,30); add(connect);
        
        enviarjButton = new JButton("Enviar"); 
        enviarjButton.setBackground(Color.black); enviarjButton.setForeground(Color.white);
        enviarjButton.setBounds(400,400,100,50); add(enviarjButton);

        credito = new JLabel("By Tuyama"); credito.setForeground(Color.white);
        credito.setBounds(250,475,100,20); add(credito);

        pack();
    }
    
    private void initEvents()
    {
        mensagemjTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_ENTER)
                    envia();
            }
        });
        enviarjButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                envia();
            }
        });
        connect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                conex.SetConexao(textoIP.getText(),Integer.parseInt(textoPorta.getText()));
                chatjTextArea.setText("");
                escreve("Chat iniciado com " + conex.getIp() + ":" + conex.getPorta());
            }
        });
        addMouseMotionListener(new MouseMotionListener() {
            public void mouseDragged(MouseEvent e) { }
            public void mouseMoved(MouseEvent e) {
                xMouse = e.getX();
                yMouse = e.getY();
            }
        });
    }
    
    private void envia(){
        if (mensagemjTextArea.getText().equals("\n"))
            conex.envia("&"+xMouse+"@"+yMouse);
        if (!mensagemjTextArea.getText().isEmpty()) {
            conex.envia(mensagemjTextArea.getText());
            escreve("Você disse: "+mensagemjTextArea.getText());
            mensagemjTextArea.setText("");
        }
    }
    private void escreve(String texto){
        chatjTextArea.append(texto+"\n");
         if (!chatjTextArea.getText().isEmpty() && !chatjTextArea.isFocusOwner())
                chatjTextArea.setCaretPosition(chatjTextArea.getText().length() - 1);
    }
    @Override
    public void update(Observable o, Object arg) {
        String Msg = conex.getMensagem();
        int MouseX, MouseY, S1, S2;
        if (!Msg.contains("&")&&!Msg.contains("@"))
            escreve(Msg);
        else {
            for (S1=0; Msg.charAt(S1)!='&'; S1++);
            for (S2=0; Msg.charAt(S2)!='@'; S2++);
            MouseX = Integer.parseInt(Msg.substring(S1+1, S2));
            MouseY = Integer.parseInt(Msg.substring(S2+1));
            credito.setBounds(MouseX,MouseY,100,20);
        }
    }
}

Observe que a estrutura deste programa usa um conceito de Design Patterns (Observable & Observer) permitindo sincronizar o envio e recibo das mensagens, permitindo a troca fluente de mensagens entre as partes envolvidas.

6. Conclusão

A programação de Aplicações Web é complexa e promissora. Seria possível escrever cursos inteiros sobre suas aplicações e conceitos, aprofundar no tema de segurança e estudar mais a fundo a dinâmica de troca de informações.

Mas creio que o pequeno post de hoje deu uma pequena abordagem do tema ao nosso leitor, que agora pode se considerar iniciado no tema.

7. Referência:

(Ataque DDOS): 

(Sockets):

(Sockets & Javascript):

(Glassfish - Web Sockets (Javascript))

(jSocket - Javascript)

(Socket.io - Alternativa)