Módulo TCP
Este módulo fornece funcionalidades para conexões TCP e TCP+TLS a partir de scripts Lua. Oferece suporte para comunicação com sockets brutos, leitura/escrita de strings, JSON e pacotes JSON com tamanho prefixado.
O módulo tcp permite:
-
Conexões TCP simples com timeout configurável
-
Conexões TLS
-
Leitura e escrita de strings simples
-
Leitura e escrita de JSON
-
Leitura e escrita de pacotes JSON com tamanho prefixado (para comunicação binária segura)
-
Resolução DNS automática para conexões TLS
Funções Disponíveis
Seção intitulada “Funções Disponíveis”tcp.connect(host, port, [timeout_secs])
Seção intitulada “tcp.connect(host, port, [timeout_secs])”Estabelece uma conexão TCP simples com um servidor remoto.
Parâmetros:
-
host(string): Endereço do host ou IP do servidor -
port(number): Porta TCP para conexão -
timeout_secs(number, opcional): Timeout em segundos (padrão: 5)
Valor de retorno:
-
Objeto
Connectionque pode ser usado para leitura/escrita -
Lança erro em caso de falha ou timeout
Exemplo:
-- Conectar a um servidor na porta 8080 com timeout de 10 segundoslocal conn = tcp.connect("servidor.exemplo.com", 8080, 10)
-- Conectar com timeout padrão (5 segundos)local conn2 = tcp.connect("192.168.1.100", 3000)tcp.connect_tls(host, port, [timeout_secs])
Seção intitulada “tcp.connect_tls(host, port, [timeout_secs])”Estabelece uma conexão TLS (SSL) com um servidor remoto.
Parâmetros:
-
host(string): Endereço do host do servidor -
port(number): Porta TLS para conexão -
timeout_secs(number, opcional): Timeout em segundos (padrão: 5)
Valor de retorno:
-
Objeto
TlsConnectionque pode ser usado para leitura/escrita -
Lança erro em caso de falha ou timeout
Exemplo:
-- Conectar via TLS na porta 443local conn = tcp.connect_tls("api.exemplo.com", 443)
-- Conectar com timeout personalizadolocal conn2 = tcp.connect_tls("servidor-seguro.com", 8443, 15)tcp.send(data)
Seção intitulada “tcp.send(data)”Envia dados através da última conexão TCP aberta com a função connect(). Esta função é mantida para compatibilidade com versões anteriores. Para maior clareza e controle, prefira a forma local conn = connect("host", porta) e use os métodos do objeto de conexão retornado (ex: conn:write_json_packet()).
Parâmetros:
data(string): Dados a serem enviados
Valor de retorno:
-
nilem caso de sucesso -
Lança erro se não houver conexão ativa
Nota: Esta função usa a última conexão TCP aberta com a função connect(). É útil para scripts simples que mantêm uma única conexão.
Exemplo:
-- Primeiro estabelece uma conexãolocal conn = tcp.connect("servidor.exemplo.com", 8080)
-- Envia dadossend("GET / HTTP/1.1\r\nHost: servidor.exemplo.com\r\n\r\n")tcp.recv()
Seção intitulada “tcp.recv()”Recebe dados da última conexão TCP aberta com a função connect() e armazenada no registro Lua. Esta função é mantida para compatibilidade com versões anteriores. Para maior clareza e controle, prefira a forma local conn = connect("host", porta) e use os métodos do objeto de conexão retornado (ex: conn:read_str() ou conn:read_json_packet()).
Parâmetros:
- Nenhum
Valor de retorno:
-
stringcom os dados recebidos -
Lança erro se não houver conexão ativa
Nota:
-
Esta função usa a última conexão TCP aberta com a função
connect(). É útil para scripts simples que mantêm uma única conexão. -
Lê até 8192 bytes por chamada. Para leitura completa, pode ser necessário chamar múltiplas vezes.
Exemplo:
-- Recebe respostalocal resposta = tcp.recv()print("Resposta recebida:", resposta)Métodos dos Objetos Connection
Seção intitulada “Métodos dos Objetos Connection”Os objetos retornados por connect() e connect_tls() possuem os seguintes métodos:
conn:read_str()
Seção intitulada “conn:read_str()”Lê uma string completa do socket até EOF.
Valor de retorno:
-
stringcom os dados lidos -
Lança erro em caso de falha de leitura
Exemplo:
local conn = tcp.connect("servidor.exemplo.com", 8080)local dados = conn:read_str()print("Dados recebidos:", dados)conn:read_json()
Seção intitulada “conn:read_json()”Lê uma string do socket e a interpreta como JSON.
Valor de retorno:
-
Valor Lua decodificado do JSON
-
Lança erro se os dados não forem JSON válido
Exemplo:
local conn = tcp.connect("api.exemplo.com", 3000)local dados_json = conn:read_json()
-- Acessar dados decodificadosprint("Status:", dados_json.status)print("Mensagem:", dados_json.message)conn:read_json_packet()
Seção intitulada “conn:read_json_packet()”Lê um pacote JSON com tamanho prefixado (formato binário).
Formato do pacote:
-
4 bytes (uint32): Tamanho dos dados JSON
-
N bytes: Dados JSON serializados
Limite de tamanho: 512KB (512.000 bytes)
Valor de retorno:
-
Valor Lua decodificado do JSON
-
Lança erro se o pacote for muito grande ou JSON inválido
Exemplo:
local conn = tcp.connect("servidor-binario.com", 9000)local pacote = conn:read_json_packet()print("Pacote recebido:", pacote)conn:write_json_packet(packet)
Seção intitulada “conn:write_json_packet(packet)”Escreve um pacote JSON com tamanho prefixado (formato binário).
Parâmetros:
packet(qualquer valor Lua): Dados a serem serializados como JSON
Valor de retorno:
-
nilem caso de sucesso -
Lança erro em caso de falha de serialização ou escrita
Exemplo:
local conn = connect("servidor-binario.com", 9000)
-- Enviar um pacote JSONlocal dados = { comando = "atualizar", id = 123, valores = {10, 20, 30}}conn:write_json_packet(dados)Informações Adicionais
Seção intitulada “Informações Adicionais”Timeout Configurável
Seção intitulada “Timeout Configurável”Todas as funções de conexão aceitam timeout personalizado. Se não especificado, usa 5 segundos como padrão.
Resolução DNS Automática
Seção intitulada “Resolução DNS Automática”A função connect_tls() resolve automaticamente o nome do host para um endereço IP antes de estabelecer a conexão.
Tamanho Máximo de Pacote
Seção intitulada “Tamanho Máximo de Pacote”Pacotes JSON com tamanho prefixado têm um limite de 512KB para prevenir ataques de negação de serviço.
Exemplos de Uso
Seção intitulada “Exemplos de Uso”Comunicação HTTP Simples
Seção intitulada “Comunicação HTTP Simples”function fazer_requisicao_http(host, porta, caminho) local conn = connect(host, porta, 10)
-- Enviar requisição HTTP local requisicao = string.format( "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", caminho, host )
-- Usar o método send (conexão está no registro) send(requisicao)
-- Ler resposta local resposta = recv()
-- Extrair corpo da resposta (simplificado) local corpo = resposta:match("\r\n\r\n(.+)$")
return corpoendCliente de API JSON
Seção intitulada “Cliente de API JSON”function consultar_api_json(endpoint, dados) local conn = connect_tls("api.exemplo.com", 443)
-- Enviar dados como pacote JSON conn:write_json_packet({ endpoint = endpoint, dados = dados, timestamp = os.time() })
-- Aguardar resposta local resposta = conn:read_json_packet()
return respostaend
-- Exemplo de usolocal resultado = consultar_api_json("/usuarios", {id = 123})if resultado.success then print("Usuário:", resultado.usuario.nome)endMonitoramento de Serviço TCP
Seção intitulada “Monitoramento de Serviço TCP”function verificar_servico_tcp(host, porta) local inicio = os.time() local sucesso, conn = pcall(connect, host, porta, 5)
if sucesso then local tempo_resposta = os.time() - inicio
-- Testar comunicação básica conn:write_json_packet({ping = true}) local resposta = conn:read_json_packet()
if resposta and resposta.pong then return { status = "online", tempo_resposta = tempo_resposta, versao = resposta.versao } end end
return { status = "offline", erro = conn -- conn contém a mensagem de erro quando pcall falha }endComunicação Bidirecional
Seção intitulada “Comunicação Bidirecional”function chat_client(host, porta) local conn = connect(host, porta)
-- Thread para receber mensagens local function receber_mensagens() while true do local mensagem = conn:read_json_packet() print("Recebido:", mensagem.texto) end end
-- Thread para enviar mensagens (simplificado) local function enviar_mensagens() while true do io.write("Digite mensagem: ") local texto = io.read() if texto == "sair" then break end
conn:write_json_packet({ tipo = "mensagem", texto = texto, timestamp = os.time() }) end end
-- Em um ambiente real, isso seria feito com corrotinas -- Esta é uma simplificação para demonstraçãoend