Pular para conteúdo

Aula 19 - Chamadas de Sistema POSIX e Programação de Sockets 🌐

Objetivo Pedagógico

Objetivo: Comunicação em nível de sistema operacional com chamadas POSIX (fork, exec, pipe), sockets de rede BSD (socket, bind, listen, accept) e multiplexação de I/O.


📑 1. Fundamentos Teóricos & Análise Técnica

A programação de sistemas em sistemas operacionais Unix-like (Linux, macOS, BSD) fundamenta-se na API padronizada POSIX (Portable Operating System Interface). A filosofia central do Unix dita que "quase tudo é um arquivo", permitindo que conexões de rede, pipes e dispositivos de hardware sejam manipulados através de descritores de arquivo inteiros (File Descriptors - FD).

  1. Gestão de Processos POSIX:
  2. fork(): Cria uma cópia exata do processo pai em um novo processo filho (Clone de memória com Copy-on-Write).
  3. execvp(): Substitui a imagem do processo atual por um novo binário executável.
  4. waitpid(): Sincroniza a finalização do processo filho, evitando processos zumbis (Zombie Processes).
  5. Sockets de Rede BSD (Berkeley Sockets):
  6. Interface de comunicação entre máquinas através do protocolo TCP/IP.
  7. O servidor segue o fluxo canônico: socket() -> bind() (vincula à porta) -> listen() (habilita fila de conexões) -> accept() (bloqueia até a chegada de um novo cliente) -> read() / write().

📐 Arquitetura Conceitual & Diagrama de Fluxo

sequenceDiagram
    autonumber
    participant Server as Servidor TCP em C (Porta 8080)
    participant Kernel as Kernel Linux (TCP Stack)
    participant Client as Cliente Remoto

    Server->>Kernel: socket() + bind(8080) + listen()
    Server->>Kernel: accept() [Bloqueia aguardando conexão]
    Client->>Kernel: TCP 3-Way Handshake (SYN, SYN-ACK, ACK)
    Kernel-->>Server: accept() Desbloqueia e Retorna novo Client_FD
    Client->>Server: Envia Dados (read no Servidor)
    Server-->>Client: Responde Dados (write no Servidor)
    Server->>Kernel: close(Client_FD)

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - File Descriptors Unix: Descritores inteiros que representam canais abertos de entrada/saída (0=stdin, 1=stdout, 2=stderr, 3+=sockets/arquivos). - Comunicação Inter-Processos (IPC): Uso de pipe() e memória compartilhada para troca de dados entre processos filhos. - Sinais do Sistema Operacional: Captura de sinais assíncronos como SIGINT, SIGTERM e SIGCHLD via sigaction. - Conversão de Endereço de Rede: Uso obrigatório de htons() (Host-to-Network Short) para converter a ordem de bytes (Endianness) para a rede.


🛠️ 2. Implementação Prática em C POSIX e Programação de Redes

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// tcp_echo_server.c (Servidor TCP Minimalista com Sockets BSD em C)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int server_fd, client_fd;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};

    // 1. Cria socket TCP (IPv4, SOCK_STREAM)
    server_fd = socket(AF_INET, SOCK_STREAM, 0);

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT); // Converte para Network Byte Order

    // 2. Vincula à porta 8080
    bind(server_fd, (struct sockaddr*)&address, sizeof(address));

    // 3. Aguarda conexões na fila
    listen(server_fd, 5);
    printf("[Servidor TCP] Escutando na porta %d...\n", PORT);

    // 4. Aceita conexão do cliente
    client_fd = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
    read(client_fd, buffer, 1024);
    printf("[Recebido]: %s\n", buffer);

    // 5. Ecoa de volta
    write(client_fd, "Mensagem recebida com sucesso!", 30);

    close(client_fd);
    close(server_fd);
    return 0;
}

💡 Análise Passo a Passo do Código

  1. Função socket(): Solicita ao Kernel um novo socket de comunicação no domínio IPv4 (AF_INET).
  2. Conversão com htons(): Garante que o número da porta 8080 seja transmitido em formato Big-Endian na rede.
  3. Comunicação com read/write: Manipula a conexão de rede exatamente como se estivesse lendo ou escrevendo em um arquivo regular.

🎯 3. Próximos Passos & Sequência Didática