Arcane.Rede
TCP, UDP, DNS e TLS — o que está abaixo do HTTP.
O Kiln fala HTTP e a Malha fala com outro serviço. Abaixo disso não havia nada: um protocolo próprio, um agente que manda uma linha por UDP, ou descobrir para onde um nome aponta pediam sair da linguagem.
E o TLS estava na lista do que não existe, na própria documentação. Ele existe agora, dos dois lados.
TCP#
adopt Arcane.Rede as Rede
action atender(conexao):
pedido := conexao.receber_linha()
conexao.enviar_linha(pedido.upper())
Rede.servir(atender, host := "0.0.0.0", porta := 9000)cliente := Rede.conectar("127.0.0.1", 9000)
cliente.enviar_linha("forja")
out cliente.receber_linha() // FORJA
cliente.fechar()O TCP não tem fronteira de mensagem#
Ele entrega um fluxo de bytes, e não mensagens. O formato mais comum para resolver isso é tamanho + corpo:
adopt Arcane.Bytes as Bytes
action mandar(conexao, texto):
dados := Bytes.de_texto(texto)
conexao.enviar(Bytes.empacotar(">u32", len(dados)))
conexao.enviar(dados)
action receber(conexao):
quanto := Bytes.desempacotar(">u32", conexao.receber_exato(4))[0]
yield Bytes.para_texto(conexao.receber_exato(quanto))Ler#
| Chamada | Faz |
|---|---|
receber(n, prazo) | o que chegou, até n bytes |
receber_exato(n, prazo) | insiste até completar n |
receber_linha(prazo, limite) | até a quebra, com teto |
receber_tudo(prazo, limite) | até o outro lado fechar |
enviar(dados) · enviar_linha(t) | manda tudo, sem devolver pela metade |
UDP#
Manda e esquece: sem conexão, sem ordem, sem garantia. É o certo para métrica, descoberta e log — onde perder um pacote custa menos que a espera de confirmar cada um.
coletor := Rede.udp(porta := 8125, escutar := yes)
chegou := coletor.receber()
out chegou["host"], chegou["dados"]
agente := Rede.udp()
agente.enviar("pedidos=42", "127.0.0.1", 8125)DNS#
out Rede.resolver("dataforge-lang.vercel.app")
// [{ip: 76.76.21.21, versao: 4}, …]
out Rede.nome_de("8.8.8.8") // dns.google
out Rede.meu_ip() // o IP com que esta máquina saiPortas#
porta := Rede.porta_livre() // livre agora
given Rede.porta_aberta("db", 5432):
out "o banco está de pé"
Rede.esperar_porta("api", 8080, prazo := 30.0) // espera subiresperar_porta substitui o "sobe o serviço e dorme dois segundos torcendo para dar tempo" de todo script de integração. Quando ela desiste, diz o que costuma ser:
erro: api:8080 não abriu em 30s.
O serviço não subiu, subiu em outra porta, ou subiu em
127.0.0.1 quando deveria ser 0.0.0.0.TLS#
// cliente
seguro := Rede.conectar("api.exemplo.br", 443, tls := yes)
// servidor
Rede.servir(atender, porta := 443,
tls := {"certificado": "cert.pem", "chave": "chave.pem"})O certificado que vence sem avisar#
Um certificado vencido derruba o site inteiro, e o aviso chega pelo cliente reclamando. Isto é o que um monitor pergunta:
ficha := Rede.certificado_de("dataforge-lang.vercel.app")
out ficha["emissor"], ficha["valido_ate"], ficha["nomes"]
given Rede.dias_ate_vencer("api.exemplo.br") smaller 14:
alertar("o certificado vence em menos de duas semanas")