📧 Comunicação entre processos: Cliente e Servidor
🎯 Objetivo de aprendizagem
- Compreender os mecanismos de comunicação entre processos (IPC) usando sockets.
- Criar um servidor e um cliente em Python.
- Identificar o papel do sistema operacional na gestão das conexões de rede.
📜 Enunciado
Neste exercício, você vai criar uma aplicação simples de comunicação entre um cliente e um servidor usando sockets em Python.
🔧 Etapa 1 – Criar um servidor simples
Um servidor:
- Abre uma "porta" (chamada de port) no seu computador.
- Aguarda uma conexão de um cliente.
- Recebe mensagens do cliente.
Código do servidor
Crie um arquivo chamado serveur.py e copie o código a seguir:
import socket
# Crée un socket TCP
serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# L'adresse IP et le port à utiliser
hote = 'localhost'
port = 12345
# Lier le socket à l'adresse
serveur.bind((hote, port))
# Écoute jusqu'à 1 connexion
serveur.listen(1)
print("[Serveur] En attente de connexion...")
# Accepter la connexion
connexion, adresse = serveur.accept()
print(f"[Serveur] Connexion de {adresse}")
# Réception des messages
while True:
message = connexion.recv(1024).decode()
if message.lower() == "exit":
print("[Serveur] Fin de la communication.")
break
print(f"[Client] {message}")
# Fermer les connexions
connexion.close()
serveur.close()
Teste
Este programa não faz nada enquanto um cliente não se conectar. Inicie o servidor com o comando:
python serveur.py
e conecte-se usando seu navegador acessando http://localhost:12345.
Você pode parar o servidor pressionando Ctrl+C no terminal.
💬 Etapa 2 – Criar um cliente
Um cliente:
- Conecta-se a um servidor (aqui via
localhoste a porta). - Envia mensagens que você digita no console.
2.1 Código do cliente
Crie um arquivo client.py:
import socket
# Crée un socket TCP
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Se connecter au serveur
client.connect(('localhost', 12345))
print("[Client] Connecté au serveur. Tapez vos messages :")
# Lire et envoyer les messages
while True:
message = input(">>> ")
client.sendall(message.encode())
if message.lower() == "exit":
break
# Fermer la connexion
client.close()
2.2 Teste
- Em um terminal: execute
python serveur.py - Em outro terminal: execute
python client.py - Troque algumas mensagens.
- Digite
exitpara encerrar.
🔁 Etapa 3 – Comunicação nos dois sentidos
Atualmente, apenas o cliente fala e o servidor escuta. Agora vamos permitir que o servidor responda.
3.1 Usando threading para escutar e escrever ao mesmo tempo
Crie um arquivo chamado serveur2.py e copie o código a seguir:
import socket
import threading
def recevoir(connexion):
while True:
try:
message = connexion.recv(1024).decode()
if not message or message.lower() == "exit":
print("[Client] a quitté la conversation.")
print("[Serveur >>>] ", end="", flush=True)
break
print(f"[Client] {message}")
print("[Serveur >>>] ", end="", flush=True)
except: # noqa: E722
break
def envoyer(connexion):
while True:
try:
message = input("[Serveur >>>] ")
connexion.sendall(message.encode())
if message.lower() == "exit":
break
except: # noqa: E722
break
# Création du serveur
serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serveur.bind(('localhost', 12345))
serveur.listen(1)
print("[Serveur] En attente de connexion...")
connexion, adresse = serveur.accept()
print(f"[Serveur] Connecté à {adresse}")
# Démarrage des threads
thread1 = threading.Thread(target=recevoir, args=(connexion,))
thread2 = threading.Thread(target=envoyer, args=(connexion,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
connexion.close()
serveur.close()
Crie um arquivo chamado client2.py e copie o código a seguir:
import socket
import threading
def recevoir(sock):
while True:
message = sock.recv(1024).decode()
if message.lower() == "exit":
print("[Serveur] a quitté la conversation.")
print("[Client >>>] ", end="", flush=True)
break
print(f"[Serveur] {message}")
print("[Client >>>] ", end="", flush=True)
def envoyer(sock):
while True:
message = input("[Client >>>] ")
sock.sendall(message.encode())
if message.lower() == "exit":
break
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 12345))
print("[Client] Connecté au serveur.")
# Démarrage des threads
thread1 = threading.Thread(target=recevoir, args=(client,))
thread2 = threading.Thread(target=envoyer, args=(client,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
client.close()
✅ Resultado esperado
- Execute
serveur2.pyem um terminal. - Execute
client2.pyem outro. - Tente trocar mensagens nos dois sentidos.
- Encerre corretamente com
exit.

📝 Etapa 4 – O sistema operacional
O sistema operacional tem um papel crucial na gestão das conexões de rede. Ele gerencia os recursos, as portas e garante que os dados sejam enviados e recebidos corretamente. O mesmo vale para as threads, que permitem executar várias tarefas em paralelo, como escutar e enviar mensagens ao mesmo tempo.
Responda às seguintes perguntas:
- No código do servidor e do cliente, em que momento o sistema operacional está envolvido?
- As threads são gerenciadas pelo sistema operacional (OS thread) ou pelo Python (application thread)?
- Por que é importante fechar as conexões corretamente?
- O que acontece se você tentar iniciar o servidor várias vezes na mesma porta sem fechá-lo?
- O que acontece se você tentar iniciar o cliente antes do servidor?