Skip to content

Network (net)

The net module in Flame provides a full-featured, asynchronous networking toolkit. It is modular, meaning you can import only the specific networking components you need, minimizing compilation overhead for embedded or lightweight projects.

The tcp module provides TcpListener and TcpSocket for raw socket communication.

import std.net.tcp
@Application(features=["tcp"])
async fn start() {
let listener = tcp.TcpListener.bind("0.0.0.0:3000")
for client in listener {
await client.write("Hello from Flame!")
}
let socket = tcp.TcpSocket.connect("example.com:80")
socket.write("GET / HTTP/1.1\r\n\r\n")
let data = socket.read()
}

The udp module provides connectionless datagram sockets.

import std.net.udp
@Application(features=["udp"])
async fn start() {
let udp = udp.UdpSocket.bind(":9000")
udp.send("Hello", "192.168.0.10:9000")
let (msg, addr) = udp.recv()
}

The http module provides a powerful asynchronous HTTP client supporting GET, POST, PUT, DELETE, PATCH, downloading, and uploading.

When you make an HTTP request, Flame returns a special Response Object. If you try to print this response directly (println(res)), it will display its internal structure: <object [text, json, status, ok]>.

To access the actual data, you must call its methods or properties:

  • res.status: The integer HTTP status code (e.g., 200, 404).
  • res.ok: A boolean indicating if the status is successful (200-299).
  • res.text(): A closure returning the raw string body of the response.
  • res.json(): A closure returning the parsed JSON formula of the response.
import std.net.http
@Application(features=["http"])
async fn app() {
let response = await http.get("https://api.github.com/users/shoya-129")
println(response.status) // Prints: 200
println(response.ok) // Prints: true
// You must call the .text() or .json() functions to extract the body
let raw_text = response.text()
println(raw_text)
// Parsing JSON directly from GET
let response2 = await http.get("https://api.github.com")
let user = response2.json()
// Making a POST request with an auto-stringified JSON payload
let postData = formula { title: "foo", body: "bar", userId: 1 }
let post_res = await http.post("https://httpbin.org/post", postData)
println(post_res.text())
}

The ws module provides a production-grade, native, high-performance WebSocket subsystem supporting both client and server roles, binary data frames (Bytes), event callbacks, streaming iterators, broadcasting, and direct bridging into std.thread channels.

📖 Dedicated Guide: For the comprehensive WebSockets manual, real-world examples, and complete API reference tables, see the WebSockets Guide.

To start a WebSocket server, bind a listener with ws.Socket.listen(addr) (or ws.listen(addr)). The returned variable s represents the listening server directly and exposes all lifecycle handlers, connection counters, and broadcasting capabilities:

import std.net.ws
let s = ws.Socket.listen("127.0.0.1:8080")
println($"Server active on {s.address} (port {s.port})")
// Triggered when a new client connects
s.onConnect((client) {
println($"[+] Client connected: {client.id} ({client.address})")
client.send("Welcome to Flame Realtime Gateway!")
})
// Triggered when a client sends a UTF-8 text message
s.onMessage((client, msg) {
println($"[{client.id}] {msg}")
// Broadcast message to all connected clients
s.broadcast($"[{client.id}]: {msg}")
})
// Triggered when a client sends binary data
s.onBinary((client, bytes) {
println($"[{client.id}] Sent binary data: {bytes.len()} bytes")
client.sendBytes(bytes)
})
// Triggered when a client disconnects
s.onClose((client, code, reason) {
println($"[-] Client {client.id} disconnected ({code})")
})
// Check total online clients
println($"Online clients: {s.connections()}")

To connect to any remote WebSocket server (Flame, Node.js, Rust, Go, Python, etc.):

import std.net.ws
let socket = ws.Socket.connect("ws://127.0.0.1:8080")
// Event-driven message handling
socket.onMessage((msg) {
println($"Incoming message: {msg}")
})
// Sending text and binary frames
socket.send("Hello Server!")
socket.sendText("Structured JSON payload")
// Synchronous blocking receive (if preferred over callbacks)
let reply = socket.recv()
println($"Received: {reply}")
// Clean shutdown
socket.close()

3. Streaming and Channel Bridging (std.thread)

Section titled “3. Streaming and Channel Bridging (std.thread)”

Flame WebSockets integrate natively with std.thread message channels via .toChannel():

import std.net.ws
import std.thread as th
let socket = ws.connect("ws://127.0.0.1:8080")
// Option A: Asynchronous stream iteration
let stream = socket.messages()
stream.forEach((msg) {
println($"Stream: {msg}")
})
// Option B: Native MPSC channel bridging
let (tx, rx) = socket.messages().toChannel()
th.spawn(|| {
while true {
let msg = rx.recv()
println($"Worker processed: {msg}")
}
})

The mqtt module provides an MQTT client, useful for IoT and automation.

import std.net.mqtt
@Application(features=["mqtt"])
async fn start() {
let client = await mqtt.Mqtt.connect("mqtt://broker.local")
await client.publish("robot/move", "forward")
await client.subscribe("sensor/temp") |msg| {
println(msg)
}
}
import std.net.dns
@Application(features=["dns"])
async fn start() {
let ip = await dns.lookup("google.com")
}
import std.net.interface
@Application(features=["net"])
async fn start() {
for iface in await interface.interfaces() {
println(iface.name)
}
}
import std.net.url
let u = await url.Url.parse("https://github.com/sohamglx/flame?branch=main")
println(u.host)
println(u.query)