A Internet está organizada em sete camadas (de acordo com um padrão OSI), cada uma das quais se preocupa com um diferente aspeto das comunicações:
Do ponto de vista do computador, um endereço IP é um inteiro. Mas quando se escreve um endereço IP para ser lido por pessoas, usa-se a base 10 e os algarismos são agrupados de forma especial que exibe a estrutura lógica do endereço (estrutura essa que não vamos discutir aqui). Eis dois exemplos de endereços IP:
172.16.254.1 (IPv4) 2001:db8:0:1234:0:567:8:1 (IPv6).Não é prático para os humanos memorizar endereços IP e por isso foi criado um serviço de rede chamado "DNS Domain Name System" que associa nomes de domínio a endereços IP. Por exemplo, o domínio ctp.di.fct.unl.pt está associado ao endereço 193.136.122.73.
Por convenção, o nome localhost representa o computador local.
Cada serviço está associado a uma porta que pode ser escolhida livremente, embora existam muitas associações padronizadas. Por exemplo: HTTP corre na porta 80, HTTPS na porta 443, FTP na porta 21, SSH na porta 22, Telnet na porta 23, BitTorrent na porta 30301.
Em 1989, foi Tim Berners-Lee que teve a ideia de aplicar à Internet a conhecida noção de hipertexto e começou a desenvolver o assunto. Criou a primeira versão do protocolo HTTP e da linguagem HTML. Em 1990, também foi ele que escreveu o primeiro protótipo de servidor Web e o primeiro protótipo de browser Web. Eis o resumo da história dos primeiros anos. O primeiro site web foi info.cern.ch e o primeiro endereço de página web foi http://info.cern.ch/hypertext/WWW/TheProject.html.
A Web é um dos vários serviços que correm na camada de aplicação da Internet. Usa os protocolos HTTP/HTTPS e um modelo de cliente/servidor. Os servidores Web estão ligados à Internet e correm um software específico (e.g. Apache ou IIS) que fica à espera de conexões. Os utilizadores ligam-se aos servidores usando um Web browser, por exemplo o Firefox, Chrome, Opera, Safari, Internet Explorer, Edge.
URL significa Uniform Resource Locator. Tem a seguinte estrutura geral:
protocolo://domínio:porta/caminho/recurso?query#fragmentoAlguns exemplos de URLs:
http://en.wikipedia.org:80/wiki/Uniform_resource_locator#History http://www.google.com/search?q=UNL http://whatismyipaddress.com/ip/193.136.122.73 http://translate.google.com/?langpair=en|pt&text=hello https://clip.unl.pt/utente/eu/fun%E7%E3o/doc%EAncia/unidade/actividade/inscri%E7%F5es/pautas?tipo_de_per%EDodo_lectivo=s&ano_lectivo=2016&per%EDodo_lectivo=2&institui%E7%E3o=97747&unidade_curricular=8147&modo=pauta
Para ver o comando GET a funcionar, vamos enviá-lo para o servidor usando a aplicação telnet (também podíamos usar a aplicação nc) e observar a resposta do servidor. Neste exemplo, abrimos uma conexão através da porta 80 do servidor ctp.di.fct.unl.pt e depois damos um comando GET a pedir o conteúdo da primeira aula teórica de LAP.
$ telnet ctp.di.fct.unl.pt 80 Trying 193.136.122.73... Connected to di73.di.fct.unl.pt. Escape character is '^]'. GET /lei/lap/teoricas/01.html <body text="#00000" bgcolor="#E0F0E0" link="#0000EE" vlink="#551A8B" #FF0000"> <HR><HR><H1>Linguagens e Ambientes de Programação (2022/2023)</H1> <HR><HR><H2>Teórica 01 (04/Mar/2020)</H2> <p>Apresentação da disciplina. <p>Discussão introdutória sobre alguns aspetos importantes da temática das Linguagens de Programação. <HR> ... ... muitas linhas omitidas ... ... Connection closed by foreign host. |
$ telnet ctp.di.fct.unl.pt 80 Trying 193.136.122.73... Connected to di73.di.fct.unl.pt. Escape character is '^]'. HEAD /lei/lap/teoricas/01.html HTTP/1.0 HTTP/1.1 200 OK Date: Thu, 04 Jun 2020 21:38:10 GMT Server: Apache/2.2.16 (Debian) Last-Modified: Sat, 14 Mar 2020 12:54:29 GMT ETag: "3ba5f-39bf-5113f1e172b40" Accept-Ranges: bytes Content-Length: 14783 Vary: Accept-Encoding Connection: close Content-Type: text/html Connection closed by foreign host. |
Do lado do cliente também era tudo estático. Nem sequer existiam formulários. O HTML previa apenas texto, imagens e hiperligações (links).
A Web dinâmica começou em 1993, quando foram introduzidos os formulários HTML (do lado do cliente) e o Common Gateway Interface (CGI) (do lado do servidor). Do lado do browser (cliente), usando formulários HTML, passou a ser possível efetuar pedidos com argumentos variáveis. Do lado do servidor, passou a ser possível correr scripts para gerar dinamicamente páginas HTML.
As linguagens Perl e C começaram por ser as mais usadas na escrita de scripts do lado do servidor. Mas logo foram desenvolvidas linguagens mais especializadas. Uma delas, o PHP, apareceu em 1995 e tornou-se rapidamente muito popular - atualmente continua a ser a linguagem mais usada do lado do servidor. Eis outras linguagens que se usam atualmente do lado do servidor: Java, ASP, Python, Ruby, Scala, TCL, JavaScript, etc.
Agora um detalhe importante dos servidores tradicionais: por cada pedido recebido, cria-se um processo independente para correr o script que vai gerar a página de resposta. Portanto, o servidor pode ficar congestionado se forem recebidos muitos pedidos num curto espaço de tempo. (Em todo o caso, demasiados acessos concorrentes à base de dados costuma ser o fator mais determinante de possíveis congestionamentos.)
Os seguintes exemplos são representativos das funcionalidades existentes a partir de 1993. Eram suportados formulários HTML com o atributo "ACTION", os servidores eram capazes de gerar páginas dinâmicas.
Exemplo 1 - O primeiro exemplo faz uma query fixa. Ao clicar nele, fazemos o browser enviar um comando GET ao servidor da Google, que gera dinamicamente a página de resposta. O browser recebe a página HTML e mostra-a.
<a href="http://www.google.com/search?q=Cat">http://www.google.com/search?q=Cat</a> |
Exemplo 2 - Vamos interrogar o servidor usando uma query variável, usando uma string indicada pelo utilizador. Usamos um formulário HTML com um atributo "ACTION" e com o botão "submit".
<FORM ID="form1" ACTION="http://www.google.com/search"> Google query: <INPUT TYPE="text" ID="q" NAME="q" VALUE="Cat"> <INPUT TYPE="submit" VALUE="Search"> </FORM> |
Neste formulário, quase tudo o que lá se encontra tem a sua razão de ser:
Mas a adição mais revolucionária foi a introdução de scripting do lado do cliente. Com scripts a correr do lado do cliente, passou a ser possível ter páginas Web realmente interativas. A interatividade proporcionada pelos formulários era muito pobre.
A primeira linguagem de scripting usada do lado do cliente foi o JavaScript. Continua a ser a mais usada nesse contexto.
Dois atributos importantes que foram adicionados ao HTML, ligados ao scripting:
Com o JavaScript passou a ser possível, por exemplo:
O uso de lógica assíncrona tem consequências dramáticas no estilo de programação! Nos programas clássicos, o programa consegue controlar todo o fluxo de execução de forma estrita. Na programação assíncrona, escreve-se código para reagir a eventos e não há possibilidade de controlar o fluxo de execução geral.
Quando um programa JavaScript corre num browser, há uma thread principal que executa o código do programa e se chama a thread dos eventos. A thread dos eventos já está implementada (não pode ser alterada). Executa continuamente um ciclo que retira e processa os eventos guardados numa fila de espera. Por cada evento, a thread invoca a função de tratamento adequada, previamente associada a esse tipo de evento. Os eventos são tratados sequencialmente e enquanto não terminar o tratamento dum evento não se inicia o tratamento do seguinte. Por isso é importante que o tratamento de cada evento seja rápido - caso contrário, a página Web terá bloqueios desagradáveis. (Para além da thread dos eventos, há algumas threads auxiliares usadas na geração de eventos, mas elas trabalham discretamente nos bastidores, e o programador não pensa nelas.)
Eis a lista completa de eventos do DOM para os quais se podem instalar tratadores de eventos numa página HTML. Os tratadores de eventos podem ser instalados nos atributos ONCLICK e ONLOAD, ou usando a função addEventListener em código JavaScript. Para criar um timer e especificar qual a função tratadora de eventos de tempo, usa-se a função setInterval.
AJAX é um mecanismo que liberta o cliente do comportamento anterior. O cliente faz o pedido e depois pode usar a resposta (assíncrona) como entender, por exemplo para atualizar uma porção da página corrente, mostrar a resposta num alerta, ou outra coisa qualquer. Se o pedido (GET) for feito usando AJAX, a página completa já não é substituída automaticamente.
O mecanismo baseia-se numa API chamada XMLHttpRequest, que está disponível para ser usada em JavaScript em todos os browsers modernos.
Os conceitos subjacentes ao AJAX foram inventados pela Microsoft por volta de 1998. A Google começou a usar AJAX de forma massiva nos seus sites em 2004, começando pelo GMail e Google Maps.
AJAX |
Eis o código do exemplo. A função showAJAX faz o seguinte: (1) cria um pedido XMLHttpRequest vazio; (2) indica como será tratada a futura resposta do servidor; (3) preenche o pedido; (4) envia o pedido. Sabemos que a resposta já está disponível quando xhttp.readyState == 4 e sabemos que o operação teve sucesso se adicionalmente xhttp.status == 200.
<SCRIPT TYPE="text/javascript"> function showAJAX(form, filenameURL) { let xhttp = new XMLHttpRequest(); // cria pedido vazio xhttp.onreadystatechange = function() { // especifica tratamento da resposta if( xhttp.readyState == 4 ) if( xhttp.status == 200 ) { form.output.value = xhttp.responseText; } else alert("Error"); }; xhttp.open("GET", filenameURL, true); // preenche o pedido xhttp.send(); // envia o pedido para o servidor } </SCRIPT> <H1>AJAX</H1> <FORM ID="form1"> <INPUT TYPE="button" VALUE="Click Me" ONCLICK="showAJAX(form, 'files/ajax.txt')"> <br /> <INPUT TYPE="text" ID="output" VALUE="" SIZE=80 READONLY> </FORM> |
function getFile(filenameURL) { let xhttp = new XMLHttpRequest(); // cria pedido vazio xhttp.open("GET", filenameURL, false); // preenche o pedido try { xhttp.send(); // envia o pedido para o servidor return xhttp.responseText; } catch(err) { return null; } } |
Mas, durante o desenvolvimento de certas aplicações Web na máquina local, faz falta realmente o aceso a ficheiros locais. O Chrome permite desligar a segurança, invocando o browser na linha de comando da forma que se indica a seguir. Passa a ser possível aceder a ficheiros dentro da pasta do utilizador ou em subpastas desta. (Para compensar a falta de segurança, é boa ideia desenvolver a aplicação numa máquina virtual.)
google-chrome --allow-file-access-from-files myPage.html
Veja aqui como conseguir acesso aos ficheiros locais usando outros browsers.
Por questões de segurança e privacidade, a comunicação AJAX só funciona se o cliente e o servidor estiverem no mesmo domínio. O exemplo AJAX anterior funcionou porque esta página está localizada em ctp.di.fct.unl.pt a pedir dados dum servidor também situado em ctp.di.fct.unl.pt. Espera-se que o administrador do domínio ctp.di.fct.unl.pt seja um profissional competente que saiba lidar com questões de segurança. Sem a restrição do "mesmo domínio", um script malicioso podia começar a testar URLs diversos e, se tivesse sorte, podia conseguir roubar ficheiros privados com dados importantes.
Contudo, a restrição do "mesmo domínio" abre exceções para ficheiros com imagens, áudio e vídeos. Existem objetos de biblioteca específicos que permitem aceder livremente a esse género de ficheiros.
Exemplo para imagens:
function loadImage(url) { // asynchronously load let im = new Image(); im.src = url; im.onload = function() { alert("Loading finished"); } } loadImage("https://upload.wikimedia.org/wikipedia/commons/e/ee/Sample_abc.jpg"); |
Exemplo para audio:
let audio = null; // global function startAudio(url) { if( audio == null ) audio = new Audio(url); audio.loop = true; audio.play(); // requires a previous user interaction with the page } function pauseAudio() { if( audio != null ) audio.pause(); } startAudio("https://filesamples.com/samples/audio/m4a/sample3.m4a"); |