const std = @import("std");
const os = std.os;
pub fn main() !void {
try run_server(4096, .{ 127, 0, 0, 1 }, 8888);
}
fn run_server(
comptime BUFFER_SIZE: usize,
host: [4]u8,
port: u16,
) ServerError!void {
const SOCK_DOMAIN = os.AF.INET;
const SOCK_TYPE = os.SOCK.STREAM;
// Make socket descriptor.
var sockfd = try os.socket(SOCK_DOMAIN, SOCK_TYPE, 0);
defer {
os.closeSocket(sockfd);
std.debug.print("closed socket {any}\n", .{sockfd});
}
std.debug.print("opened socket {any}\n", .{sockfd});
// Bind socket to address.
const sockaddr = @bitCast(os.sockaddr, os.sockaddr.in{
.family = SOCK_DOMAIN,
.port = std.mem.nativeToBig(u16, port),
.addr = @bitCast(u32, host),
// .zeros = ...
});
try os.bind(sockfd, &sockaddr, @sizeOf(@TypeOf(sockaddr)));
try os.listen(sockfd, 1);
std.debug.print(
"listening at @{any}.{any}.{any}.{any}:{any}\n",
.{ host[0], host[1], host[2], host[3], port },
);
// Accept an incoming connection.
while (true) {
const sockfd_accept = try os.accept(sockfd, null, null, 0);
defer {
os.closeSocket(sockfd_accept);
std.debug.print("connection to socket {any} closed\n", .{sockfd_accept});
}
std.debug.print("accepted connection to socket {any}\n", .{sockfd_accept});
var buffer: [BUFFER_SIZE]u8 = undefined;
// Receive incoming messages.
while (true) {
const msg_len = try std.os.recv(sockfd_accept, &buffer, 0);
if (msg_len == 0) break;
const socket_msg = buffer[0..msg_len];
std.debug.print(" Received message:\n {s}\n", .{socket_msg});
// Echo received message.
_ = try std.os.send(sockfd_accept, socket_msg, 0);
}
}
}
const ServerError = os.SocketError || os.BindError || os.ListenError || os.AcceptError || os.RecvFromError || os.SendError;