---
title: "std.net.Stream em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/stdlib/std.net.stream-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/stdlib/std.net.stream-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Guia completo do std.net.Stream em Zig em português. Socket TCP bidirecional com interfaces Reader/Writer e exemplos práticos."
date: "2026-02-21"
author: "Zig Brasil"
---

# std.net.Stream em Zig — Referência e Exemplos

Guia completo do std.net.Stream em Zig em português. Socket TCP bidirecional com interfaces Reader/Writer e exemplos práticos.


# std.net.Stream — Conexão TCP Bidirecional

O `std.net.Stream` representa uma conexão TCP estabelecida e bidirecional. Ele encapsula um descritor de socket do sistema operacional e fornece métodos para leitura e escrita de dados, além de implementar as interfaces `Reader` e `Writer` do `std.io`, permitindo usar todas as funções de I/O genéricas do Zig.

## Visão Geral

```zig
const std = @import("std");
const net = std.net;
const Stream = net.Stream;
```

### Estrutura

```zig
pub const Stream = struct {
    handle: std.posix.socket_t,

    pub fn read(self: Stream, buffer: []u8) ReadError!usize
    pub fn readv(self: Stream, iovecs: []std.posix.iovec) ReadError!usize
    pub fn write(self: Stream, buffer: []const u8) WriteError!usize
    pub fn writev(self: Stream, iovecs: []std.posix.iovec_const) WriteError!usize
    pub fn close(self: Stream) void

    pub fn reader(self: Stream) std.io.GenericReader(...)
    pub fn writer(self: Stream) std.io.GenericWriter(...)
};
```

O `Stream` é um tipo leve (apenas um `handle`) que pode ser copiado livremente. Chamar `close()` em qualquer cópia fecha a conexão para todas.

## Funções Principais

### Leitura

```zig
// Lê bytes no buffer, retorna quantidade lida (0 = fim)
pub fn read(self: Stream, buffer: []u8) ReadError!usize

// Lê usando scatter (múltiplos buffers)
pub fn readv(self: Stream, iovecs: []std.posix.iovec) ReadError!usize

// Retorna Reader compatível com std.io
pub fn reader(self: Stream) Reader
```

### Escrita

```zig
// Escreve bytes, retorna quantidade escrita
pub fn write(self: Stream, buffer: []const u8) WriteError!usize

// Escreve usando gather (múltiplos buffers)
pub fn writev(self: Stream, iovecs: []std.posix.iovec_const) WriteError!usize

// Retorna Writer compatível com std.io
pub fn writer(self: Stream) Writer
```

### Controle

```zig
// Fecha o socket
pub fn close(self: Stream) void

// Obtém informações do socket
pub fn getLocalAddress(self: Stream) !net.Address
pub fn getRemoteAddress(self: Stream) !net.Address
```

## Exemplo 1: Cliente que Envia e Recebe Dados

```zig
const std = @import("std");
const net = std.net;

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const stdout = std.io.getStdOut().writer();

    // Conecta ao servidor
    const stream = net.tcpConnectToHost(allocator, "example.com", 80) catch |err| {
        try stdout.print("Falha na conexão: {}\n", .{err});
        return;
    };
    defer stream.close();

    // Usa a interface Writer para enviar HTTP
    const writer = stream.writer();
    try writer.writeAll("GET / HTTP/1.1\r\n");
    try writer.writeAll("Host: example.com\r\n");
    try writer.writeAll("Connection: close\r\n");
    try writer.writeAll("\r\n");

    // Usa a interface Reader para ler a resposta
    const reader = stream.reader();
    var buf: [4096]u8 = undefined;

    // Lê primeira linha (status HTTP)
    if (try reader.readUntilDelimiterOrEof(&buf, '\n')) |linha| {
        try stdout.print("Status: {s}\n", .{std.mem.trim(u8, linha, "\r")});
    }

    // Conta bytes totais da resposta
    var total_bytes: usize = 0;
    while (true) {
        const n = try reader.read(&buf);
        if (n == 0) break;
        total_bytes += n;
    }

    try stdout.print("Total recebido: {d} bytes\n", .{total_bytes});
}
```

## Exemplo 2: Protocolo de Mensagens com Tamanho Prefixado

```zig
const std = @import("std");
const net = std.net;

const Protocolo = struct {
    stream: net.Stream,

    // Envia mensagem com prefixo de tamanho (4 bytes, big-endian)
    pub fn enviarMensagem(self: Protocolo, dados: []const u8) !void {
        const writer = self.stream.writer();
        const tamanho: u32 = @intCast(dados.len);

        // Escreve o tamanho primeiro
        try writer.writeInt(u32, tamanho, .big);
        // Depois os dados
        try writer.writeAll(dados);
    }

    // Recebe mensagem com prefixo de tamanho
    pub fn receberMensagem(self: Protocolo, buf: []u8) !?[]u8 {
        const reader = self.stream.reader();

        // Lê o tamanho (4 bytes)
        const tamanho = reader.readInt(u32, .big) catch |err| {
            if (err == error.EndOfStream) return null;
            return err;
        };

        if (tamanho > buf.len) return error.BufferMuitoPequeno;

        // Lê exatamente 'tamanho' bytes
        const slice = buf[0..tamanho];
        try reader.readNoEof(slice);
        return slice;
    }
};

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Demonstra o protocolo com um fixedBufferStream (simulação)
    var buf_dados: [1024]u8 = undefined;
    var stream_buf = std.io.fixedBufferStream(&buf_dados);

    // Simula escrita de mensagem
    const writer = stream_buf.writer();
    const mensagem = "Olá, protocolo!";
    const tamanho: u32 = @intCast(mensagem.len);
    try writer.writeInt(u32, tamanho, .big);
    try writer.writeAll(mensagem);

    // Simula leitura
    stream_buf.reset();
    const reader = stream_buf.reader();
    const tam_lido = try reader.readInt(u32, .big);
    var buf_recv: [256]u8 = undefined;
    try reader.readNoEof(buf_recv[0..tam_lido]);

    try stdout.print("Mensagem recebida ({d} bytes): {s}\n", .{
        tam_lido,
        buf_recv[0..tam_lido],
    });
}
```

## Exemplo 3: Proxy TCP Simples

```zig
const std = @import("std");
const net = std.net;

fn encaminhar(origem: net.Stream, destino: net.Stream) void {
    var buf: [4096]u8 = undefined;
    while (true) {
        const n = origem.read(&buf) catch break;
        if (n == 0) break;
        destino.writer().writeAll(buf[0..n]) catch break;
    }
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const porta_local: u16 = 9000;
    const host_destino = "example.com";
    const porta_destino: u16 = 80;

    const addr = try net.Address.parseIp4("127.0.0.1", porta_local);
    var server = try addr.listen(.{ .reuse_address = true });
    defer server.deinit();

    std.debug.print("Proxy escutando em :{d} -> {s}:{d}\n", .{
        porta_local, host_destino, porta_destino,
    });

    while (true) {
        const conn = server.accept() catch continue;
        std.debug.print("Nova conexão de {}\n", .{conn.address});

        // Conecta ao destino
        const destino = net.tcpConnectToHost(
            allocator,
            host_destino,
            porta_destino,
        ) catch |err| {
            std.debug.print("Erro ao conectar ao destino: {}\n", .{err});
            conn.stream.close();
            continue;
        };

        // Em produção, use threads separadas para cada direção
        encaminhar(conn.stream, destino);

        destino.close();
        conn.stream.close();
    }
}
```

## Módulos Relacionados

- [std.net](/stdlib/std-net/) — Visão geral de networking
- [std.net.Address](/stdlib/std-net-address/) — Tipos de endereço
- [std.io.Reader](/stdlib/std-io-reader/) — Interface Reader
- [std.io.Writer](/stdlib/std-io-writer/) — Interface Writer
- [std.http](/stdlib/std-http/) — HTTP sobre Stream

## Tutoriais e Receitas Relacionados

- [Tutorial: Networking com Zig](/tutoriais/networking/)
- [Receita: Protocolo Binário TCP](/receitas/protocolo-tcp/)
