// 23_networking.ruchy - Network programming and socket operations
import std::net
import std::socket
fn main() {
println("=== Network Programming ===\n")
// TCP Server
println("=== TCP Server ===")
async fn tcp_server() {
let listener = net::TcpListener::bind("127.0.0.1:8080")
println("Server listening on 127.0.0.1:8080")
loop {
match await listener.accept() {
Ok((stream, addr)) => {
println(f"New connection from {addr}")
spawn handle_client(stream)
},
Err(e) => println(f"Accept error: {e}")
}
}
}
async fn handle_client(mut stream) {
let mut buffer = [0; 1024]
loop {
match await stream.read(buffer) {
Ok(0) => {
println("Client disconnected")
break
},
Ok(n) => {
let message = String::from_utf8(buffer[0..n])
println(f"Received: {message}")
// Echo back
await stream.write(f"Echo: {message}".as_bytes())
},
Err(e) => {
println(f"Read error: {e}")
break
}
}
}
}
// TCP Client
println("\n=== TCP Client ===")
async fn tcp_client() {
let mut stream = await net::TcpStream::connect("127.0.0.1:8080")
println("Connected to server")
// Send message
await stream.write("Hello, server!".as_bytes())
// Read response
let mut buffer = [0; 1024]
let n = await stream.read(buffer)
let response = String::from_utf8(buffer[0..n])
println(f"Server response: {response}")
stream.close()
}
// UDP Socket
println("\n=== UDP Socket ===")
fn udp_server() {
let socket = net::UdpSocket::bind("127.0.0.1:9000")
println("UDP server listening on 127.0.0.1:9000")
let mut buffer = [0; 1024]
loop {
match socket.recv_from(buffer) {
Ok((n, addr)) => {
let message = String::from_utf8(buffer[0..n])
println(f"UDP received from {addr}: {message}")
// Send response
socket.send_to(f"ACK: {message}".as_bytes(), addr)
},
Err(e) => println(f"UDP error: {e}")
}
}
}
fn udp_client() {
let socket = net::UdpSocket::bind("127.0.0.1:0") // Random port
let server_addr = "127.0.0.1:9000"
socket.send_to("Hello UDP!".as_bytes(), server_addr)
let mut buffer = [0; 1024]
let (n, _) = socket.recv_from(buffer)
let response = String::from_utf8(buffer[0..n])
println(f"UDP response: {response}")
}
// HTTP Server
println("\n=== HTTP Server ===")
async fn http_server() {
let server = net::HttpServer::new("0.0.0.0:3000")
server.route("GET", "/", |req, res| {
res.status(200)
.header("Content-Type", "text/html")
.body("<h1>Welcome to Ruchy HTTP Server!</h1>")
})
server.route("GET", "/api/users", |req, res| {
let users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]
res.json(users)
})
server.route("POST", "/api/users", |req, res| {
let body = req.json()
println(f"Creating user: {body}")
res.status(201)
.json({ id: 3, name: body.name })
})
server.middleware(|req, res, next| {
println(f"{req.method} {req.path}")
let start = now()
next()
let duration = now() - start
println(f"Request took {duration}ms")
})
println("HTTP server running on http://localhost:3000")
await server.listen()
}
// WebSocket Server
println("\n=== WebSocket Server ===")
async fn websocket_server() {
let server = net::WebSocketServer::new("127.0.0.1:8765")
server.on_connection(|ws, req| {
println(f"WebSocket connection from {req.remote_addr}")
ws.on_message(|msg| {
println(f"WS message: {msg}")
match msg.type {
"text" => ws.send_text(f"Echo: {msg.data}"),
"binary" => ws.send_binary(msg.data),
"ping" => ws.pong(),
_ => {}
}
})
ws.on_close(|code, reason| {
println(f"WS closed: {code} - {reason}")
})
ws.on_error(|error| {
println(f"WS error: {error}")
})
})
println("WebSocket server running on ws://localhost:8765")
await server.listen()
}
// WebSocket Client
async fn websocket_client() {
let ws = await net::WebSocket::connect("ws://localhost:8765")
ws.on_open(|| {
println("WebSocket connected")
ws.send_text("Hello from client!")
})
ws.on_message(|msg| {
println(f"Received: {msg.data}")
})
// Send periodic pings
spawn async {
loop {
await sleep(30000)
ws.ping()
}
}
await ws.wait()
}
// HTTP Client with retries
println("\n=== HTTP Client with Retries ===")
async fn http_client_with_retry(url, max_retries = 3, backoff = 1000) {
let mut retries = 0
while retries < max_retries {
try {
let response = await net::http::get(url)
if response.status == 200 {
return Ok(response)
} else {
throw f"HTTP {response.status}"
}
} catch e {
retries += 1
if retries < max_retries {
println(f"Retry {retries}/{max_retries} after {backoff}ms")
await sleep(backoff * retries)
} else {
return Err(f"Failed after {max_retries} retries: {e}")
}
}
}
}
// Load balancer
println("\n=== Load Balancer ===")
struct LoadBalancer {
backends: list,
current: int = 0,
strategy: string = "round_robin"
}
impl LoadBalancer {
fn next_backend(mut self) {
match self.strategy {
"round_robin" => {
let backend = self.backends[self.current]
self.current = (self.current + 1) % self.backends.len()
backend
},
"random" => {
let index = rand_int(0, self.backends.len())
self.backends[index]
},
"least_connections" => {
// Find backend with least active connections
self.backends.min_by(|b| b.active_connections)
},
_ => self.backends[0]
}
}
async fn forward_request(self, request) {
let backend = self.next_backend()
println(f"Forwarding to {backend.url}")
try {
let response = await net::http::forward(request, backend.url)
response
} catch e {
// Try another backend
println(f"Backend failed: {e}, trying another")
self.forward_request(request)
}
}
}
// Rate limiter
println("\n=== Rate Limiter ===")
struct RateLimiter {
max_requests: int,
window_ms: int,
requests: map = {}
}
impl RateLimiter {
fn allow(mut self, client_id) {
let now = current_time()
let window_start = now - self.window_ms
// Clean old entries
if client_id in self.requests {
self.requests[client_id] = self.requests[client_id]
.filter(t => t > window_start)
} else {
self.requests[client_id] = []
}
// Check rate limit
if self.requests[client_id].len() >= self.max_requests {
false
} else {
self.requests[client_id].append(now)
true
}
}
}
// DNS lookup
println("\n=== DNS Operations ===")
let ip = net::dns::lookup("example.com")
println(f"example.com resolves to {ip}")
let hostname = net::dns::reverse_lookup("8.8.8.8")
println(f"8.8.8.8 is {hostname}")
// Network interface information
println("\n=== Network Interfaces ===")
let interfaces = net::get_interfaces()
for iface in interfaces {
println(f"Interface: {iface.name}")
println(f" IP: {iface.ip}")
println(f" MAC: {iface.mac}")
println(f" Status: {iface.status}")
}
// Port scanning
async fn port_scan(host, start_port, end_port) {
println(f"Scanning {host} ports {start_port}-{end_port}")
let open_ports = []
for port in start_port..=end_port {
let result = await net::TcpStream::connect_timeout(
f"{host}:{port}",
100 // 100ms timeout
)
if result.is_ok() {
open_ports.append(port)
println(f" Port {port}: OPEN")
result.unwrap().close()
}
}
open_ports
}
// Example usage (commented out for safety)
// await port_scan("localhost", 8000, 8100)
}