Servidor TCP simples em Python

Servidor TCP simples em Python

A pouco tempo resolvi me aprofundar mais Python e olhar para essa linguagem com outros olhos. Pensando nisso, comprei vários livros, comecei a ler vários artigos e vários assuntos diferentes, não ficando apenas no mundo Python + Django.

Nessa minha busca por outros ares, bati num assunto bem legal, Redes e Python. Sendo assim, além dos artigos de Django que venho postando, vou iniciar uma série de artigos relacionados a esse assunto.

Antes de botar a mão na massa, quero deixar claro uma coisa. Não sou o dono da verdade e o objetivo de todo post técnico que eu crio é repassar conhecimento. Portanto, deixe seu comentário e faça sua crítica (com conteúdo por favor) 🙂

Você que usa Django, já parou para pensar como o “runserver” funciona? Eu já, mas tenho certeza que, assim como eu, muita gente só passou o olho no código e não parou para tentar entender o que acontece ali. Pois bem, vou mostrar aqui, de forma absurdamente simplificada, como que um servidor TCP trabalha. Então, vamos construir um juntos.

A primeira coisa que você vai fazer é importar as bibliotecas que vamos precisar e, como o Python é FO!@, só vamos precisar de duas:

import socket
import threading

Em seguida, vamos definir duas variáveis:

bind_ip, bind_port = (‘0.0.0.0’, 9999)

O passo seguinte é criar um novo socket:

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Com o socket definido, informar o IP e a porta que separamos no início e em seguida vamos dizer ao servidor para começar a ouvir as requisições:

server.bind((bind_ip, bind_port))

# O número 5 representa a quantidade máxima de conexões
server.listen(5)

O passo seguinte dar uma posição do que está acontecendo:

print(“[*] Listening on {0}:{1}”.format(bind_ip, bind_port))

Retornar informação para o client é fundamental para saber o que está acontecendo, o próximo passo é criar uma função que retorna uma mensagem muito simples:

def handle_client(client_socket):
    # exibe o que for enviado pelo client
    request = client_socket.recv(1024)
    print(“[*] Received: {0}”.format(request))
    # envia um pacote de volta
    client_socket.send(“Hello world!”)
    client_socket.close()

O próximo, e último passo, é receber a conexão do cliente:

while True:
    client, addr = server.accept()
    accept_connection = (
        “[*] Accept connection from: {0}:{1}”.format(
             addr[0], addr[1]
        )
    )
    print(accept_connection)
    # Coloca a thread de cliente em ação para tratar
    # os dados de   entrada
    client_handler = threading.Thread(
        target=handle_client, args=(client, )
    )
    client_handler.start()

Agora, no terminal, coloque seu servidor para rodar:

python tcp_server.py

Se tudo der certo, você verá a seguinte linha:

[*] Listening on 0.0.0.0:9999

Depois disso, abra seu navegador coloque o endereço 0.0.0.0:9999

Volte ao terminal, e veja a “mágica” acontecer!

[*] Listening on 0.0.0.0:9999
[*] Accept connection from: 127.0.0.1:55142
[*] Accept connection from: 127.0.0.1:55143
[*] Accept connection from: 127.0.0.1:55144
[*] Accept connection from: 127.0.0.1:55145
[*] Received: GET / HTTP/1.1
Host: 0.0.0.0:9999
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,es;q=0.6,pt-BR;q=0.4,pt;q=0.2
[*] Received: GET /favicon.ico HTTP/1.1
Host: 0.0.0.0:9999
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Accept: */*
Referer: http://0.0.0.0:9999/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,es;q=0.6,pt-BR;q=0.4,pt;q=0.2

Parece bobo, é realmente muito bobo, mas é bem bacana fazer isso pela primeira vez! 🙂

Informações importantes e relevantes:

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *