Your SlideShare is downloading. ×
Rede em Python




   Rede em Python


Antonio Sérgio Nogueira




  Presidente Prudente
         2009
Rede em Python

                                      Rede em Python

1. A REDE – Existe uma palavra por trás de toda essa...
Rede em Python

com certos protocolos de rede (TCP/IP, UDP/IP, etc..). Eles permitem que programas aceitem
conexões para r...
Rede em Python

conexão local use como hostname localhost.

getpeername() - retorna o endereço IP e a porta na qual o sock...
Rede em Python

urllib                                            busca páginas web


4.Programação com SOCKET – como já f...
Rede em Python




Detalhando as instruções dos programas anteriores:

sockobj=socket(AF_INET, SOCK_STREAM) – cria um sock...
Rede em Python

 data_received=clisocket.recv(1024)
 print data_received
 clisocket.send(data_to_send)
 clisocket.close()
...
Rede em Python

   return time.ctime(time.time())

class MyClientHandler(SocketServer.BaseRequestHandler):
   def handle(s...
Rede em Python

portsock=socket(AF_INET,SOCK_STREAM)
portsock.bind((myhost,myport))
portsock.listen(5)
mainsocks.append(po...
Rede em Python

# servidor UDP - serverudp.py
import socket
port = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_DGR...
Rede em Python

import socket, struct, sys, time
TIME1970 = 2208988800L
client = socket.socket(socket.AF_INET, socket.SOCK...
Rede em Python

  outputfile.write(data)
outputfile.close()
pagehandler.close()

9. HTTP – é um protocolo simples baseado ...
Rede em Python

Para executar este servidor HTTP basta entrar no seu browser e digitar: //http:localhost/ , se quiser
obte...
Rede em Python

To:asergionogueira@gmail.com
Subject: Nao tenho nada pra dizer.
Aqui eh a mensagem.
'''
>>> server.sendmai...
Rede em Python

de codificar 8bits em 7bits, duas codificações são definidas pelo MIME a codificação Base64 e a
codificaçã...
Rede em Python


Protocolo POP3 – como normalmente o servidor de email localiza-se numa máquina da rede, para
buscar um em...
Rede em Python

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
67 68 69 70 7...
Rede em Python

>>> for id, sub in subs:print id, sub

113 der test [0/1] - Post Description (1/1)
114 ATEST
115 test
116 ...
Upcoming SlideShare
Loading in...5
×

Acessando a Internet com o Python

8,172

Published on

Acessando a Ineternet com o Python, socket, protocolos etc...

Published in: Education, Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
8,172
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
414
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Transcript of "Acessando a Internet com o Python"

  1. 1. Rede em Python Rede em Python Antonio Sérgio Nogueira Presidente Prudente 2009
  2. 2. Rede em Python Rede em Python 1. A REDE – Existe uma palavra por trás de toda essa tecnologia que chegou ao mercado – a rede(network). Não importa se você está transferindo um arquivo ou navegando com seu browser favorito, toda esta tecnologia de rede está por trás disto, o Python tem um número grande de módulos para trabalhar com ela, que em baixo nível é acessada através de um conceito chamado socket. Neste tópico iremos falar sobre a comunicação entre programas na rede. Não é necessário dois computadores em rede para testar os programas, basta usarmos a rede para estabelecer a comunicação entre processos num mesmo computador. Quando falamos em rede encontramos alguns termos que mostraremos a seguir: Socket é o ponto de conexão da rede. Quando queremos nos conectar a uma rede através de um browser devemos criar um socket e instruí-lo a conectar ao computador servidor que também possue um socket que fica aguardando as requisições, um socket pode receber e enviar mensagens. Cada socket em uso é ligado a um número de IP e a um número de Porta. IP é uma sequência de 4 números na faixa de 0 a 255( 234.112.130.1), sequência que endereça o computador na rede. Existem números de IP que são reservados um deles é o IP “127.0.0.1” que é o localhost, ou seja o computador local, usado para fazer a conexão entre programas que estão rodando na mesma máquina. O uso do IP pode ser facilitado através dos DNS. DNS (Domain Name Servers) são computadores que fazem a conversão dos nomes em endereços da rede. Porta é um número de 0 a 65535, que serve para determinar uma conversação em particular, os números de 0 a 1023 são reservados para serviços de rede conhecidos( a porta 80 é usada pela WEB). Diferentes protocolos são usados na rede, um deles é o HTTP, usado para comunicar-se entre Browsers e Servidores Web, que é construído em cima do protocolo TCP, cuja construção gira em torno do protocolo IP. Protocolo – formato das mensagens e regras de conexão que atuam em cima dos sockets. Quando transmitimos dados entre dois programas podemos escolher entre o TCP e o UDP. O protocolo TCP cria uma conexão persistente entre os dois pontos o que garante o envio e recebimento correto e em ordem dos dados. Já o protocolo UDP não é orientado a conexão, mas é mais rápido e menos seguro, podendo os dados não chegar ou serem recebidos desordenadamente . 1.1 Níveis de Rede – a rede está dividida em 7 níveis ou camadas de acordo com o padrão OSI/ISO, o qual sugere os seguintes níveis: Físico – define as informações necessárias para transferir os dados sobre os componentes físicos, como os cabos. Data Link - define a forma como os dados são transferidos dos componente e para os componentes. Correção de erros ponto a ponto são definidos neste nível. Rede – organiza a rede assinalando endereços distintos para seus componentes, então a informação pode ser roteada para o computador certo. O protocolo IP trabalha nesta camada. Transporte – empacota os dados e faz os dados chegar ao destino sem erros. TCP e UDP são os protocolos que implementam essas responsabilidades. Sessão – Manipula cada conexão individual feita pelas máquinas. Apresentação – usada para sobrepor as diferenças como formatos de inteiros em diferentes plataformas, Python tem o módulo struct para fazer isto. Aplicação – implementa o produto final, sua aplicação. Cliente FTP, SMTP/POP3 manipulador de email e HTTP browser são exemplos de aplicações completas que rodam na rede. 2. Sockets – São objetos que fornecem um padrão portável para aplicações em redes e trabalham
  3. 3. Rede em Python com certos protocolos de rede (TCP/IP, UDP/IP, etc..). Eles permitem que programas aceitem conexões para receber e enviar dados. Cada socket tem um tipo que define o protocolo que implementa o ambiente onde o socket é usado. Os três tipos mais populares são stream, datagram e raw. O tipo stream e datagram pode interfacear diretamente o protocolo TCP. Já o tipo raw é a interface do protocolo IP. O módulo socket é uma interface objeto base que permite acessar a rede tipo BSD no nível inferior. Ele fornece várias métodos e chamadas de erro para trabalhar com a rede de computadores. socket(family, type [,protocol]) – este método cria e retorna um novo objeto socket. O valor de family pode ser AF_INET para a Protocolo IPv4 como o TCP e o UDP. O valor de type pode ser stream para protocolo TCP(SOCK_STREAM) e datagram para protocolo UDP(SOCK_UDP). O terceiro argumento opcional só é usado com raw sockets(SOCK_RAW e family AF_INET). gethostname() retorna o nome do computador na qual o programa está executando. >>>import socket >>>socket.gethostname() 'sssssssss' gethostbyname(name) retorna o endereço IP, checando primeiro se o computador corrente pode fazer a conversão, se não for possível esta requisição é feita a um computador remoto DNS, se não for possível retorna erro. >>>socket.gethostbyname('www.python.org') '132.151.1.90' getservbyname(service, protocol) retorna o número da porta do serviço. >>>socket.getservbyname('http','tcp') 80 Número das Portas: 80 - HTTP – Web pages 119 – NNTP – Usenet news 20/21 – FTP transfer/FTP control – Transferência de arquivos 25 – SMTP – Envio de e-mail 110 – POP3 – Busca de e-mail 143 – IMAP4 – Busca de e-mail 23 – TELNET – Linha de Comando 70 – Gopher – Transferência de Documentos accept() - aceita uma nova conexão e retorna os valores: o novo objeto socket e e o endereço do socket está comunicando. bind(hostmane, port) – conecta o socket ao endereço da porta. close() - fecha o socket. connect(hostname, port) – conecta-se com outro socket, que pode ser externo ou local. Para
  4. 4. Rede em Python conexão local use como hostname localhost. getpeername() - retorna o endereço IP e a porta na qual o socket está conectado. getsocketnome()- retorna o endereço IP da porta do próprio socket. listen(max_connections) – inicia ouvindo a porta e fica esperando outras conexões. O sistema Operacional recusa novas conexões quando ela atingir o valor máximo de conexões. makefile([modem [,buffersize]]) – cria um objeto arquivo para ler e escrever, útil em protocolos orientados a stream. recvfrom(buffersize) – retorna uma string de dados do socket, usado para protocolo UDP. send(string) – envia uma string de dados pelo socket. Usada em protocolo UDP. sendto(string,(hostname,port)) – envia string para o servidor hostname na porta port. setblocking(flag) – bloqueia todas as leituras e escritas no socket 3. Trabalhando com sockets – para programar sockets temos as portas padrões definidas anteriormente, de tal forma que programas como browsers saibam de antemão em qual porta se comunicar. Desta forma temos na NET uma estrutura cliente/servidor, de um lado máquinas que ficam rodando programas para atender requisitos de conexão(servidores) e do outro lado máquinas que utilizam estes serviços (clientes). O servidor é uma máquina que executa um programa ( normalmente um servidor web) que fica ouvindo a porta 80 tratando as requisições através de processos threads ou forks. Já o Cliente é uma máquina, que executa um programa, que quer falar com um servidor específico que tem um nome e usa a porta 80 para comunicação(browser). Na NET temos alguns clientes como o Internet Explorer, o Firefox, etc... Geralmente vários clientes podem se conectar através de um socket, e funcionalmente protocolos que rodam em cima deles fazem uma tarefa bastante familiar como: navegar na Internet, ler e-mail, postar mensagens em grupos, fazer downloads, etc... Os protocolos são mensagens estruturadas que atuam em cima dos sockets e tornam as comunicações mais robustas, evitando travamentos, estabelecendo conexões persistentes, etc... O TCP/IP o mais usado na internet, foi criado pelo Departamento de Defesa do EUA. A parte IP do protocolo cuida do roteamento dos pacotes enviando eles através da rede. Já o TCP cuida da principal forma de comunicação sobre a Internet fornecendo uma confiável distribuição de pacotesa na sequência. Já o protocolo UDP (USER DATAGRAM PRTOCOL), é outro protocolo que prove uma conexão não confiável mas bastante rápida, ele é útil para fluxo de mídia (streaming media), onde atrasos e repetições não são desejáveis. Em Python temos vários módulos que trabalham com protocolos diferentes, eles são nomeados normalmente da seguinte forma: XXXlib.py onde XXX é o nome do protocolo. Vejamos alguns módulos: httplib,ftplib,nntplib protocolos HTTP, FTP e NNTP poplib,imaplib,smtlib protocolos POP, IMAP e SMTP (e-mail) socket comunicação via internet cgi módulo que suporta script CGI no lado servidor
  5. 5. Rede em Python urllib busca páginas web 4.Programação com SOCKET – como já falamos anteriormente temos dois tipos de programas: um que recebe as requisições (servidor) e outro que pede as informações (cliente). Para criarmos a conexão entre máquinas, devemos importar o módulo socket, criar o objeto socket, e chamar os métodos do objeto para enviar e receber as comunicações. Programa Servidor: socketserver.py from socket import * # importamos o módulo socket myhost='' #definimos o endereço do host(servidor) - '' - localhost myport=50006 #definimos a porta de comunicação sockobj=socket(AF_INET,SOCK_STREAM) #criamos o objeto socket TCP sockobj.bind((myhost, myport)) #conectamos ao servidor o número da porta sockobj.listen(5) #ouvimos a conexão, permitimos até 5 conexões while True: #ouvimos a porta até o processo encerrar connection, address=sockobj.accept() #esperamos a próxima conexão do cliente print 'Servidor Conectado por', address #sinalizamos uma nova conexão while True: data=connection.recv(1024) #recebemos os dados print data #imprimimos os dados if not data: break #término da recepção connection.send("Echo=>"+data) #retornamos o dado ao cliente connection.close() #fechamos a comunicação Programa Cliente:socketclient.py import sys #importa módulo funções do sistema from socket import * #importa módulo socket serverhost='localhost' #define o servidor, se o servidor estiver em outra #máquina basta colocar o IP da máquina serverport=50006 #porta de conexão message=['Ola Mundo'] #mensagem a ser enviada ao servidor if len(sys.argv)>1: #define o nome do servidor como 1o. argumento do serverhost=sys.argv[1] #script if len(sys.argv)>2: #uma mensagem para cada argumento,2o. em diante message=sys.argv[2:] sockobj=socket(AF_INET,SOCK_STREAM) #gera o objeto socket sockobj.connect((serverhost,serverport)) #conecta-se ao servidor for line in message: sockobj.send(line) #envia mensagem data=sockobj.recv(1024) #recebe retorno da mensagem print 'Cliente Recebeu:',repr(data) #imprime mensagem sockobj.close() #fecha conexão
  6. 6. Rede em Python Detalhando as instruções dos programas anteriores: sockobj=socket(AF_INET, SOCK_STREAM) – cria um socket TCP/IP padrão da internet, AF_INET define como protocolo de endereçamento o IP e SOCK_STREAM define como protocolo de transferência o protocolo TCP. sockobj.bind((myhost,myport)) – associa ao objeto socket o endereço IP e o número da porta na qual estabeleceremos a comunicação. No lado servidor o nome pode ser em branco para definir que o servidor roda na máquina local, já no lado do cliente devemos definir o endereço IP, que pode ser localhost quando cliente e servidor estão na mesma máquina. sockobj.listen(5) – inicia a monitoração da comunicação, definindo o número de requisições que o servidor suporta na sua lista de espera. O número 5 é mais que suficiente para receber as comunicações, uma vez que cada requisição chega ao servidor ela é tratada e retirada da fila. Loop servidor - o servidor entra num loop aguardando a comunicação através do comando connection, address=sockobj.accept(), uma vez ela estabelecida um novo objeto é criado para conexão(connection) e os dados então podem ser recebidos através do comando data=connection.recv(1024) e transmitidos através do comando connection.send("Echo=>"+data). Cliente – no lado do cliente temos a transmissão da mensagem através da função send e a recepção através da função recv, do objeto sockobj. connection.close() fecha a conexão do servidor e sockobj.close() encerra a conexão do cliente. Outro exemplo simples: # TCP cliente import socket clisocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) clisocket.connect(("localhost", 8888)) clisocket.send('comuniquei') data = clisocket.recv(1024) clisocket.close() print "Recebi o dado: ", data # TCP servidor import socket svrsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) svrsocket.bind(("", 8888)) svrsocket.listen(5) while 1: data_to_send = "Dados do servidor" data_received='' clisocket, address = svrsocket.accept() print "endereco: ", address
  7. 7. Rede em Python data_received=clisocket.recv(1024) print data_received clisocket.send(data_to_send) clisocket.close() 5. Conexão com vários clientes simultâneos – quando vários clientes se conectam ao servidor se o tempo de resposta for longo a conexão falha. Para resolver este problema a melhor solução é usar um processamento paralelo através de threads, multiplexagem ou forks. O processo forks é similar ao processo de threads e é disponível apenas em sistemas Linux, por isso não abordaremos aqui. O único cuidado que devemos tomar com processos forks é que eles devem ser encerrados para que não fiquem executando no sistema como processos Zumbi. 5.1 Threads – as threads rodam paralelamente e compartilham a memória global e na maioria das vezes são mais eficientes que as forks e trabalham bem mas plataformas Unix e Windows e ao encerrar não deixam processos zumbis rodando. from socket import * # importa módulo socket import thread,time #importa módulo thread myhost='' #define nome do host como local myport=50008 #define a porta sockobj=socket(AF_INET,SOCK_STREAM) sockobj.bind((myhost, myport)) sockobj.listen(5) def tratamentocliente(connection): time.sleep(5) while True: data=connection.recv(1024) print data if not data: break connection.send("Echo=>"+data) connection.close() while True: connection, address=sockobj.accept() #abre a conexão gerando um objeto connection print 'Servidor Conectado', address thread.start_new(tratamentocliente,(connection,)) # inicia um processo para tratar essa conexão Para testar este servidor e ver ele executando paralelamente abra duas ou mais janelas do DOS e execute o programa cliente. O programa é executado paralelamente deixando os processos na fila por 5s. 5.2 Usando a biblioteca SocketServer – é uma biblioteca que facilita escrever programas servidores com threads ou forks. import SocketServer, time myhost='' myport=50008 def now():
  8. 8. Rede em Python return time.ctime(time.time()) class MyClientHandler(SocketServer.BaseRequestHandler): def handle(self): print self.client_address,now() time.sleep(5) while True: data=self.request.recv(1024) if not data: break self.request.send('Echo %s em %s' %(data,now())) self.request.close() myaddr=(myhost,myport) server=SocketServer.ThreadingTCPServer(myaddr,MyClientHandler) server.serve_forever() Estamos usando o módulo SocketServer neste exemplo, e para mudar de thread para fork basta substituir a classe para ForkingTCPServer. 5.3 Multiplexagem – para executar os programas paralelamente o sistema operacional na realidade particiona cada tarefa e executa um pedaço de cada, simulando que está executando elas ao mesmo tempo. Na realidade a execução paralela só ocorre em máquinas que tenham mais de uma CPU. Em python ainda podemos fazer este tipo de paralelismo executado pela forks ou pela thread usando a biblioteca select, que verifica qual socket está pronto para transmitir e então dá atenção a esta parte do programa. A função select é de longe o mecanismo mais simples. Esta função tem (de fato), quatro argumentos: três "listas" de sockets, e um tempo limite. As três listas socket indicam o interesse em ler, escrever e eventos de exceção para cada soquete listado. A função irá retornar sempre que um desses eventos é acionado. Se nada acontecer dentro do tempo limite, a função simplesmente retorna. O resultado da função select () é de três listas que lhe diz que soquete que disparou eventos. Sua aplicação terá uma rotina de tratamento para cada tipo de evento esperado. Esse manipulador irá realizar tarefas diferentes, dependendo da sua aplicação. Se uma ligação tem uma necessidade de manter informações de estado, você provavelmente vai acabar escrevendo uma máquina do Estado para lidar com as transições entre diferentes comportamentos. Desta forma um ciclo de eventos simples será suficiente que é acoplado a um laço que limita este tempo em segundos(sugestão 30s). #servidor com select import sys,time from select import select from socket import socket,AF_INET,SOCK_STREAM def now(): return time.ctime() myhost='' myport=50007 if len(sys.argv)==3: myshost,myport=sys.argv[:1] mainsocks,readsocks,writesocks=[],[],[]
  9. 9. Rede em Python portsock=socket(AF_INET,SOCK_STREAM) portsock.bind((myhost,myport)) portsock.listen(5) mainsocks.append(portsock) readsocks.append(portsock) while True: readables,writeables,exceptions=select(readsocks,writesocks,[]) for sockobj in readables: if sockobj in mainsocks: newsock,address=sockobj.accept() print 'Conectado',address,id(newsock) readsocks.append(newsock) else: data=sockobj.recv(1024) if not data: sockobj.close() readsocks.remove(sockobj) else: sockobj.send(data) Outro exemplo: import select import socket App_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) App_Socket.bind("", 50008) App_Socket.listen(5) while 1: readable_sockets = [App_Socket] writable_sockets = [] r, w, err = select.select(readable_sockets, writable_sockets, [], 0) if r: client, address = service.accept() client.send("data") client.close() O select permite que as chamadas ao socket como accept ou recv não bloqueie o programa. Maiores detalhes consultar biblioteca. Atenção: existe um método em socket chamado setblocking capaz de posicionar os comandos para bloquear ou não o comando (bloquear significa deixar o comando aguardando a recepção de um dado). Existe um sistema chamado TWISTED que implementa estas rotinas de servidor assíncrono de uma forma eficaz (TWISTED – servidor de rede dirigido a eventos e distribuído sob licença do MIT). 6. Protocolo UDP – para troca de pequenas mensagens entre máquinas sem a necessidade de confiabilidade, podemos usar o protocolo UDP, neste protocolo se a mensagem não chegar ao destino ela é descartada. Programa servidor: serverudp.py
  10. 10. Rede em Python # servidor UDP - serverudp.py import socket port = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Aceita datagramas UDP na porta dada, enviado por qualquer cliente s.bind(("", port)) print "Esperando DADOS na porta:", port while True: # Recebe até 1024 bytes no datagrama data, addr = s.recvfrom(1024) print "Recebido:", data, "de:", addr Programa cliente: clientudp.py # cliente UDP - clientUDP import socket port = 50007 host = "localhost" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto("Olá servidor. Estou no ar.", (host, port)) O método bind não é usado nesta comunicação. Utilize estas linhas de programa para enviar grandes mensagens: BUFSIZE = 1024 while msg: bytes_sent = s.sendto(msg[:BUFSIZE], (host, port)) msg = msg[bytes_sent:] 7. Protocolo SNTP -este protocolo de comunicação SIMPLE NETWORK TIME PROTOCOL é um protocolo de sincronização dos computadores da rede(NTP). Na Internet temos servidores de horário de dois níveis, ou camadas, de servidores de horário NTP (Network Time Protocol) disponíveis na Internet. Definido pelo RFC (Request for Comments) 1305. Os de primeiro nível destinam-se basicamente a agir como servidores de horário de origem para os servidores de horário do segundo nível. Os servidores de horário de primeiro nível também podem ser capazes de fornecer serviços de tempo essenciais para a missão. Alguns servidores de horário de primeiro nível acesso restrito. Os servidores de horário de segundo nível destinam-se às necessidades gerais de serviço de tempo SNTP. Os servidores de horário de segundo nível geralmente permitem o acesso público. É recomendado que você utilize servidores de horário de segundo nível para uma configuração normal do servidor de horário SNTP, pois eles normalmente estão localizados em uma rede mais próxima que pode produzir atualizações mais rápidas e mais precisas(veja: Microsoft Ajuda e Suporte). O NTP utiliza a porta 123, de modo que essa porta seja aberta em um firewall ou um roteador para garantir a comunicação adequada com o servidor NTP. No Brasil acesse o servidor de horário de 2o. Nível: Brazilian Research Network 200.144.121.33:ntp.cais.rnp.br #gettimeserverSNTP.py
  11. 11. Rede em Python import socket, struct, sys, time TIME1970 = 2208988800L client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) data = 'x1b' + 47 * '0' client.sendto(data, (sys.argv[1], 123)) data, address = client.recvfrom(1024) if data: print 'Resposta recebida de:', address t = struct.unpack('!12I', data)[10] t -= TIME1970 print 'tTime=%s' % time.ctime(t) Para executar este programa digite numa janela do DOS: python gettimeserverSNTP.py ntp.cais.rnp.br Um SNTP começa com o cliente enviando um datagrama UDP de 48 bytes que começa com o byte 'x1b', seguido por nulos. O servidor responde com um datagrama de 48 bytes ou 12 palavras de 4 bytes. 11 destes bytes são o número de segundos passados até hoje, basta então subtrair o número de segundos até 1970(no python a data inicial de contagem de segundos começa a partir de 1970) e pronto basta usar a função ctime do módulo time e temos a data e hora do sistema. 8. Acessando URL – se você quiser pegar um documento de uma URL na WEB, o Python fornece os módulos urllib e urlparse ferramentas para processar URL( Uniform Resource Locator). O módulo urllib é uma interface para recuperar dados através da WEB, e suporta protocolos HTTP, FTP e conexões gopher usando sockets. Veja este exemplo que retorna uma página da WEB: from urllib import urlopen doc = urlopen("http://www.python.org").read( ) print doc Ou este exemplo: import urllib page=urllib.urlopen(“http://www.python.org”).read() page.readline() teste também, no lugar de page.readline() : for key,value in page.headers.items(): print key,”=”,value Copiando uma página da WEB para um arquivo: #urlcopiasite.py import urllib pagehandler = urllib.urlopen("http://www.python.org") outputfile = open("site.html", "wb") while 1: data = pagehandler.read(512) if not data: break
  12. 12. Rede em Python outputfile.write(data) outputfile.close() pagehandler.close() 9. HTTP – é um protocolo simples baseado em texto e usado em aplicações WEB. Ambos servidor e browser WEB implementam este protocolo. Para trabalhar com este protocolo o browser deve abrir a conexão e enviar um cabeçalho de requisição para o servidor WEB. Esta requisição é um simples formulário de texto que contém os métodos requisitados(GET, POST, PUT...), o nome do arquivo que será aberto, etc... O servidor interpreta a requisição e retorna a resposta ao cliente. Esta resposta contém o número de versão do HTTP, e informações como cookies, tipo e tamanho do documento que será enviado (http://www.w3.org/Protocols). Para construir WEB Servers você pode usar os seguintes módulos: – SocketServer – é um socket base para servidor IP. – BaseHTTPServer – Infraestrutura para os próximos dois módulos. – SimpleHTTPServer – Permite desenvolver um servidor WEB simples. – CGIHTTPServer – Permite a implementação de servidor HTTP com CGI O módulo SocketServer possui ferramentas de trabalho que simplificam a tarefa de escrever servidores de rede. Ao invés de ter que implementar servidores usando um socket(módulo de baixo nível), este módulo fornece quatro classes de servidor de base que implementam as interfaces com os protocolos utilizados na maioria das vezes: TCPServer, UDPServer, StreamRequestHandler e DatagramRequestHandler. Todas essas classes processam requisições sincronamente. Cada requisição deve ser completada antes que novas requisições possam ser iniciadas, o que não é aceitável quando existem tarefas muito longas, o que deixaria o processo lento. Então elas podem ser tratadas em threads separadas, usando as classes: ThreadingTCPServer, ThreadingUDPServer, ForkingUDPServer e ForkingTCPServer. (Citado acima no item 5.2) O módulo BaseHTTPServer define duas classes base para implementar servidor HTTP(WEB Server). É construído em cima do módulo SockerServer e raramente é usado diretamente. Vamos mostrar em seguida um Servidor HTTP usando a classe BaseHTTPRequestHandler. Programar servidor com BaseHTTPServer: import BaseHTTPServer htmlpage = """ <html><head><title>Web Page</title></head> <body>Alo Mundo Python</body> </html>""" notfound = "Arquivo nao encontrado" class WelcomeHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): if self.path == "/": self.send_response(200) self.send_header("Content-type","text/html") self.end_headers() self.wfile.write(htmlpage) else: self.send_error(404, notfound) httpserver = BaseHTTPServer.HTTPServer(("",80), WelcomeHandler) httpserver.serve_forever()
  13. 13. Rede em Python Para executar este servidor HTTP basta entrar no seu browser e digitar: //http:localhost/ , se quiser obter o erro digite: //http:localhost// . 10. FTP – o protocolo FTP(File Transfer Protocol) é a forma mais popular de transferir dados ente máquinas através da rede. Ele pode trabalhar permitindo apenas que usuários cadastrados transfiram dados ou que qualquer um transfira os dados. Para implementar este tipo de cliente usamos o módulo FTP ftplib. Esta implementação FTP utiliza duas portas uma de controle e outra de transferência de dados, evitando assim problemas de travamento. #ftpsimples.py import ftplib ftp = ftplib.FTP('ftp.puc-rio.br') ftp.login() ftp.cwd('pub/puc/ftp') ftp.retrlines('LIST') #visualiza diretorio de arquivos file = open('puc.txt', 'w') ftp.retrbinary('RETR Estatistica-FTP-Arquivo-Semanal.txt', file.write, 2000) ftp.quit() Para fazer um Upload: import ftplib ftp = ftblib.FTP(“ftp.puc-rio.br”) ftp.login("username", "password") filename = "index.html" ftp.storlines("STOR " + filename, open(filename)) filename = "app.exe " ftp.storbinary("STOR " + filename, open(filename, "rb"), 1024) 11. SMTP/POP3/IMAP – quando falamos nestes protocolos estamos falando em protocolos usados na internet para trabalhar com emails (SMTP e POP3). O SMTP(Simple Mail Transfer Protocol) é usado oficialmente para transferir emails pela Internet (coloca os emails nas caixas de email dos servidores de email) e o protocolo POP(Post Office Protocol) é usado para permitir acessar remotamente a caixa de email lendo e escrevendo email dos servidores de email. O IMAP(Internet Message Acess Protocol) é outro protocolo que está sendo usado para leitura de emails, ou seja acessa o email em um servidor remoto como se ele fosse local. Python fornece um sofisticado conjunto de classes para construção de mensagens de e-mail. Geralmente podemos dizer que um e-mail é uma string com um formato pré-definido. Tudo que você necessita para enviar um e-mail é uma string formatada, um endereço mail to e o módulo smtplib. Veja exemplo: >>> import smtplib >>> server=smtplib.SMTP('gmail-smtp-in.l.google.com',25) >>> para='asergionogueira@ig.com.br' >>> de='ninguem@nada.com' >>> msg=''' From:ninguem@nada.com
  14. 14. Rede em Python To:asergionogueira@gmail.com Subject: Nao tenho nada pra dizer. Aqui eh a mensagem. ''' >>> server.sendmail(de,para,msg) {} >>> server.close() A classe SMTP do módulo smtplib serve para se conectar com um servidor de e-mails, caso você tenha um servidor de e-mail local, basta usar 'localhost'. E 25 é a porta padrão do SMTP. Um e-mail consiste de um conjunto de cabeçalhos e um corpo( a mensagem). Os cabeçalhos são enviados geralmente como um par de valores separados por ':' e um espaço (exemplo: 'Subject: OI') Você pode criar uma mensagem conforme o padrão RFC2822 usando o Python através da classe message. O objeto Message atua como um dicionário mapeando a mensagem cabeçalho e valor, e também tem o corpo do texto que é o payload. >>> from email.Message import Message >>> message=Message() >>> message['Subject']='Ola' >>> message.set_payload('Corpo da mensagem') >>> print str(message) From nobody Tue Sep 08 14:44:32 2009 Subject: Ola Corpo da mensagem >>> A seguir mostramos alguns cabeçalhos padrão da mensagem definida pela norma RFC2822: Cabeçalho Exemplo Propósito To To: Sergio<sergio@ig.com.br> Endereço da pessoa que receberá a mensagem From From: Jose<jose@ig.com.br> Endereço da pessoa que enviou o email. Date Date:Sun, 16 Jan 2009 14:56:32 A data que a mensagem foi enviada. Subject Subject: Ola O título ou o sumário da mensagem. Cc Cc:sergio@gmail.com, Endereço de pessoas que devem Jose<jose@gmail.com> receber a mensagem, mesmo que não são endereçadas para elas. Corpo da mensagem Mensagem com até 1000 caracteres * S ó p o d e m o s u s a r o s p r i m e i r o s 1 2 7 c a r a c t e r e s A S C I I. Para enviar mensagems com outros caracteres e com gráficos e arquivos binários usamos a extensão do RFC2822 chamada de MIME(Multipurpose Internet Mail Extension), padronizado através da norma RFC 1521. A parte mais importante do MIME são as codificações, que fornecem uma forma
  15. 15. Rede em Python de codificar 8bits em 7bits, duas codificações são definidas pelo MIME a codificação Base64 e a codificação quoted-printable. >>> from email.MIMEImage import MIMEImage >>> filename = 'inverno.jpg' >>> msg = MIMEImage(open(filename).read(),name=filename) >>> msg['To']='asergionogueira@gmail.com' >>> msg['From']='sergio@nada.com' >>> msg['Subject']='Foto' >>> print str(msg) From nobody Wed Sep 09 14:28:44 2009 Content-Type: image/jpeg; name="inverno.jpg" MIME-Version: 1.0 Content-Transfer-Encoding: base64 To: asergionogueira@gmail.com From: sergio@nada.com Subject: Foto / 9j/4AAQSkZJRgABAgEAYABgAAD/7RBKUGhvdG9zaG9wIDMuMAA4QklNA+0KUmVzb2x 1dGlvbgAA AAAQAGAAAAABAAEAYAAAAAEAAThCSU0EDRhGWCBHbG9iYWwgTGlnaHRpbmcgQ W5nbGUAAAAABAAA AHg4QklNBBkSRlggR2xvYmFsIEFsdGl0dWRlAAAAAAQAAAAeOEJJTQPzC1ByaW50IEZs YWdzAAAA CQAAAAAAAAAAAQA4QklNBAoOQ29weXJpZ2h0IEZsYWcAAAAAAQAAOEJJTScQFEp hcGFuZXNlIFBy aW50IEZsYWdzAAAAAAoAAQAAAAAAAAACOEJJTQP1F0NvbG9yIEhhbGZ0b25lIFNldH RpbmdzAAAA SAAvZmYAAQBsZmYABgAAAAAAAQAvZmYAAQChmZoABgAAAAAAAQAyAAAAAQB aAAAABgAAAAAAAQA1 AAAAAQAtAAAABgAAAAAAAThCSU0D+BdDb2xvciBUcmFuc2ZlciBTZXR0aW5ncwAAA HAAAP////// //////////////////////8D6AAAAAD/////////////////////////////A+gAAAAA//////// /////////////////////wPoAAAAAP////////////////////////////8D6AAAOEJJTQQIBkd1 aWRlcwAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHg1VUkwgb3ZlcnJpZGVzAA AABAAAAAA4QklN BA== >>> server=smtplib.SMTP('gmail-smtp-in.l.google.com',25) >>> server.sendmail('asergionogueira@ig.com.br','asergionogueira@gmail.com',str(msg)) {} >>> server.close() >>> Veja no exemplo acima como ficou a mensagem codificada através da função MIME e depois observe que enviamos ela pela rede e fechamos a conexão. Quando temos um email com múltiplos arquivos podemos usar a classe email.MimeMultipart em conjunção com as outras classes email.Mime*.
  16. 16. Rede em Python Protocolo POP3 – como normalmente o servidor de email localiza-se numa máquina da rede, para buscar um email do servidor de email você precisa de um protocolo, no caso o POP3(Post Office Protocol revisão 3) que está em declínio de popularidade. O protocolo foi definido pela norma RFC1725. O módulo poplib implementa clientes POP3, a referência desta biblioteca descreve o protocolo como obsoleto, e recomenda o uso do IMAP4 se o servidor aceitar. >>> m=poplib.POP3_SSL('pop.gmail.com') >>> m.user('asergionogueira') '+OK send PASS' >>> m.pass_(getpass.getpass()) Warning: Problem with getpass. Passwords may be echoed. Password: suasenha '+OK Welcome.' >>> nummessages=len(m.list()[1]) >>> print nummessages 635 >>> print m.retr(2)[1] # um valor entre 1 e 635 ['Received: by 10.86.33.4 with HTTP; Wed, 11 Jun 2008 19:18:24 -0700 (PDT)', 'Message-ID: <7c7187c10806111918m1bfbc6fbl332ef19575fa29d7@mail.gmail.com>', 'Date: Wed........ ….......................... …......................... -=_Part_24989_12520194.1213237104237--'] Protocolo IMAP4 - O outro protocolo para acessar um caixa de correio em um servidor remoto é o IMAP, o Internet Message Access Protocol. A mais recente revisão do IMAP é definido no RFC 3501, e tem características muito mais de POP3. É também a ganhar popularidade em mais de POP3. A principal diferença entre POP3 e IMAP é que o POP3 é projetado para agir como uma caixa de correio e só detém seu e-mail por um tempo até você coletá-lo. IMAP é projetada para manter seu e-mail permanentemente armazenados no servidor. Entre outras coisas, você pode criar pastas no servidor, para diferentes email, e buscá-los. Com o IMAP, um cliente de email só precisa expor esses recursos do IMAP, mas não é necessário implementá-las por conta própria. Mantendo o seu email no servidor faz com que seja mais fácil manter a configuração de email, mesmo enquanto se move a partir do computador para computador. Claro, você ainda pode baixar o correio para o seu computador e depois apagá-lo da servidor, como acontece com POP3. O IMAP4 é implementado através do módulo imaplib e está detalhado em RFC-1730 e RFC-2060. Iremos aqui mostrar apenas como recuperar mensagens. >>> import getpass,imaplib >>> m=imaplib.IMAP4_SSL('imap.gmail.com',993) >>> m.login('asergionogueira@gmail.com','suasenha') ('OK', ['asergionogueira@gmail.com authenticated (Success)']) >>> status,count=m.select('INBOX') >>> print status,count OK ['650'] >>> status,data=m.search(None,'ALL') >>> print data ['1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
  17. 17. Rede em Python 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 …............. 7 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650'] >>> status,data=m.fetch(650,'(RFC822)') #escolhi o de numero 650 >>>print data[0][1] Delivered-To: asergionogueira@gmail.com Received: by 10.101.69.8 with SMTP id w8cs414785ank; Thu, 10 Sep 2009 08:13:30 -0700 (PDT) Received: by 10.141.33.21 with SMTP id l21mr510299rvj.88.1252595610052; Thu, 10 Sep 2009 08:13:30 -0700 (PDT) Return-Path: <naoresponda@fuvest.com.br> Received: from sharedrelay01.alog.com.br (sharedrelay.alog.com.br [200.155.24.164]) by mx.google.com with ESMTP id 5si3842282ywh.6.2009.09.10.08.13.29; Thu, 10 Sep 2009 08:13:29 -0700 (PDT) Received................................. …............................................ YnNwOzwvUD48L1REPjwvVFI+PC9UQk9EWT48L1RBQkxFPg== >>> m.close() ('OK', ['Returned to authenticated state. (Success)']) >>> m.logout() ('BYE', ['LOGOUT Requested']) >>> 12. Protocolo NNTP – a biblioteca nntplib do Python implementa o lado cliente do protocolo NNTP. O protoco NNTP ou Network News Transfer Protocol é um protocolo da Internet para grupos de discussão da chamada usenet. Foi definido inicialmente pela RFC-977; vide também RFC-3977. Especifica o modo de distribuição, busca, recuperação e postagem de artigos usando um sistema de transmissão confiável. Para clientes de leitura de notícias, o NNTP habilita a recuperação de artigos armazenados em um banco de dados centralizado, permitindo aos assinantes a opção de selecionar somente os artigos nos quais estão interessados. Em seguida um exemplo: >>> import nntplib >>> s=nntplib.NNTP('freenews.netfront.net') >>> resp,count,first,last,name=s.group('1.test') >>> print 'grupo',name,'tem',count, 'artigos de',first,'ate',last grupo 1.test tem 188 artigos de 112 ate 304 >>> resp,subs=s.xhdr('subject',first+'-'+last) >>> print resp 221 subject matches follow (NOV) >>> print subs [('113', 'der test [0/1] - Post Description (1/1)'), ('114', 'ATEST'), ('115', 'test'), ('116', 'etse'), ('117', 'TEST POSTING'), ('118', 'Please take a look at this and be your hone boss its totally Free'), ('119', 's'), ('120', 'd'), ('121', 'test'), ('122', '1test22'), ('123', 'RIZLA+ CIGARETTE ROLLING PAPERS & MORE'), ('124', 'RIZLA+ CIGARETTE ROLLING PAPERS & MORE'), ('125', 'test0201'), ('126', 'Test - do no................... …........................................ ar'), ('304', 'bau bau')]
  18. 18. Rede em Python >>> for id, sub in subs:print id, sub 113 der test [0/1] - Post Description (1/1) 114 ATEST 115 test 116 etse 117 TEST POSTING 118 Please take a look at this and be your hone boss its totally Free 119 s......... …............. 302 test 303 zomaar 304 bau bau >>>s.quit() 13. Protocolo Telnet – é um terminal de emulação de terminal para redes TCP/IP. O Telnet conecta seu computador a um servidor remoto, permitindo você enviar comandos através dele para o computador remoto. O módulo telnetlib fornece uma classe telnet que implementa o protocolo Telnet, veja RFC854. Veja exemplo a seguir. import getpass import sys import telnetlib HOST = "rt.njabl.org" user = raw_input("Enter your remote account: ") password = getpass.getpass() tn = telnetlib.Telnet(HOST,2501) tn.read_until("login: ") tn.write(user + "n") if password: tn.read_until("Password: ") tn.write(password + "n") tn.write("lsn") tn.write("exitn") print tn.read_all() Referência Bibliográfica: Python Cookbook – O'Relly www.python.org

×