Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Last active November 6, 2019 20:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewrk/4ca4badce653619d0804464c2e400220 to your computer and use it in GitHub Desktop.
Save andrewrk/4ca4badce653619d0804464c2e400220 to your computer and use it in GitHub Desktop.
simple tcp chat server demo from the live stream
const std = @import("std");
const net = std.net;
const fs = std.fs;
const os = std.os;
pub const io_mode = .evented;
pub fn main() anyerror!void {
const allocator = std.heap.direct_allocator;
const req_listen_addr = net.IpAddress.parse("127.0.0.1", 0) catch unreachable;
var server = net.TcpServer.init(net.TcpServer.Options{});
defer server.deinit();
try server.listen(req_listen_addr);
std.debug.warn("listening at {}\n", server.listen_address);
var room = Room{
.clients = std.AutoHashMap(*Client, void).init(allocator),
.lock = std.Mutex.init(), // TODO fix std.event.Lock and use that instead.
};
while (true) {
const client_file = try server.accept();
const client = try allocator.create(Client);
client.* = Client{
.file = client_file,
.handle_frame = async client.handle(&room),
};
var held_lock = room.lock.acquire();
defer held_lock.release();
try room.clients.putNoClobber(client, {});
}
}
const Client = struct {
file: fs.File,
handle_frame: @Frame(handle),
fn handle(self: *Client, room: *Room) !void {
try self.file.write("server: welcome to teh chat server\n");
while (true) {
var buf: [100]u8 = undefined;
const amt = try self.file.read(&buf);
const msg = buf[0..amt];
try room.broadcast(msg, self);
}
}
};
const Room = struct {
clients: std.AutoHashMap(*Client, void),
lock: std.Mutex,
fn broadcast(room: *Room, msg: []const u8, sender: *Client) !void {
var held_lock = room.lock.acquire();
defer held_lock.release();
var it = room.clients.iterator();
while (it.next()) |entry| {
const client = entry.key;
if (client == sender) continue;
// TODO make this not give SIGPIPE.
// Also, `try` here is no good because it should still write to the other clients!
try client.file.write(msg);
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment