Skip to content

Instantly share code, notes, and snippets.

@lithdew
Created October 6, 2020 14:56
Show Gist options
  • Save lithdew/eb3e1372573c33430a022e2e69b56e33 to your computer and use it in GitHub Desktop.
Save lithdew/eb3e1372573c33430a022e2e69b56e33 to your computer and use it in GitHub Desktop.
pike (windows): benchmark tcp client and server
const std = @import("std");
const os = std.os;
const net = std.net;
const windows = os.windows;
const ws2_32 = windows.ws2_32;
const pike = @import("pike.zig");
fn socket(address: net.Address, socket_type: u32) !os.fd_t {
const fd = try os.socket(address.any.family, socket_type, os.IPPROTO_TCP);
errdefer os.close(fd);
var flag: c_ulong = 1;
if (ws2_32.ioctlsocket(fd, ws2_32.FIONBIO, &flag) != 0) {
return windows.unexpectedWSAError(ws2_32.WSAGetLastError());
}
return fd;
}
fn close(fd: anytype) void {
switch (@TypeOf(fd)) {
windows.HANDLE => windows.CloseHandle(fd),
ws2_32.SOCKET => assert(ws2_32.closesocket(fd) == 0),
else => @compileError("Unknown file descriptor type " ++ @TypeOf(fd)),
}
}
fn connect(file: *pike.File, address: net.Address) callconv(.Async) !void {
pike.os.connect(file.handle, &address.any, address.getOsSockLen()) catch |err| switch (err) {
error.WouldBlock => {},
else => return err,
};
file.waker.wait(.{ .write = true });
try pike.os.getsockoptError(file.handle);
file.schedule(.{ .write = true });
}
fn write(file: *pike.File, buf: []const u8) callconv(.Async) !usize {
var overlapped = windows.OVERLAPPED{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
.OffsetHigh = 0,
.hEvent = null,
};
pike.os.WriteFile(file.handle, buf, &overlapped) catch |err| switch (err) {
error.WouldBlock => {
std.debug.print("Write would block!\n", .{});
file.waker.wait(.{ .write = true });
},
else => return err,
};
file.schedule(.{ .write = true });
return overlapped.InternalHigh;
}
fn read(file: *pike.File, buf: []u8) callconv(.Async) !usize {
var overlapped = windows.OVERLAPPED{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
.OffsetHigh = 0,
.hEvent = null,
};
pike.os.ReadFile(file.handle, buf, &overlapped) catch |err| switch (err) {
error.WouldBlock => {
std.debug.print("Read would block!\n", .{});
file.waker.wait(.{ .read = true });
},
else => return err,
};
file.schedule(.{ .read = true });
return overlapped.InternalHigh;
}
const print = std.debug.print;
const assert = std.debug.assert;
fn loop(driver: *pike.Driver, stopped: *bool) callconv(.Async) !void {
defer stopped.* = true;
const address = try net.Address.parseIp("127.0.0.1", 9000);
var file = pike.File{ .driver = driver, .handle = try socket(address, os.SOCK_STREAM) };
defer close(@ptrCast(ws2_32.SOCKET, file.handle));
try driver.register(&file, .{ .read = true, .write = true });
try connect(&file, address);
std.debug.print("Successfully connected!\n", .{});
var buf: [65536]u8 = undefined;
while (true) {
const n = try write(&file, &buf);
// std.debug.print("Sent {}\n", .{n});
}
}
pub fn main() !void {
var driver = try pike.Driver.init(.{});
defer driver.deinit();
_ = try windows.WSAStartup(2, 2);
defer windows.WSACleanup() catch {};
var stopped = false;
var frame = async loop(&driver, &stopped);
while (!stopped) {
try driver.poll(10000);
}
try nosuspend await frame;
}
const std = @import("std");
const os = std.os;
const net = std.net;
const mem = std.mem;
const windows = os.windows;
const ws2_32 = windows.ws2_32;
const pike = @import("pike.zig");
fn socket(address: net.Address, socket_type: u32) !os.fd_t {
const fd = try os.socket(address.any.family, socket_type, os.IPPROTO_TCP);
errdefer os.close(fd);
var flag: c_ulong = 1;
if (ws2_32.ioctlsocket(fd, ws2_32.FIONBIO, &flag) != 0) {
return windows.unexpectedWSAError(ws2_32.WSAGetLastError());
}
return fd;
}
fn close(fd: anytype) void {
switch (@TypeOf(fd)) {
windows.HANDLE => windows.CloseHandle(fd),
ws2_32.SOCKET => assert(ws2_32.closesocket(fd) == 0),
else => @compileError("Unknown file descriptor type " ++ @TypeOf(fd)),
}
}
const Connection = struct {
address: net.Address,
file: pike.File,
};
fn accept(file: *pike.File) !Connection {
var address: net.Address = undefined;
var address_len: os.socklen_t = @sizeOf(net.Address);
while (true) {
const handle = pike.os.accept(file.handle, &address.any, &address_len, os.SOCK_NONBLOCK | os.SOCK_CLOEXEC) catch |err| switch (err) {
error.WouldBlock => {
file.waker.wait(.{ .read = true });
continue;
},
else => return err,
};
file.schedule(.{ .read = true });
var flag: c_ulong = 1;
if (ws2_32.ioctlsocket(@ptrCast(ws2_32.SOCKET, handle), ws2_32.FIONBIO, &flag) != 0) {
return windows.unexpectedWSAError(ws2_32.WSAGetLastError());
}
return Connection{ .address = address, .file = .{ .handle = handle, .driver = file.driver } };
}
}
fn write(file: *pike.File, buf: []const u8) callconv(.Async) !usize {
var overlapped = windows.OVERLAPPED{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
.OffsetHigh = 0,
.hEvent = null,
};
pike.os.WriteFile(file.handle, buf, &overlapped) catch |err| switch (err) {
error.WouldBlock => {
std.debug.print("Write would block!\n", .{});
file.waker.wait(.{ .write = true });
},
else => return err,
};
file.schedule(.{ .write = true });
return overlapped.InternalHigh;
}
fn read(file: *pike.File, buf: []u8) callconv(.Async) !usize {
var overlapped = windows.OVERLAPPED{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
.OffsetHigh = 0,
.hEvent = null,
};
pike.os.ReadFile(file.handle, buf, &overlapped) catch |err| switch (err) {
error.WouldBlock => {
std.debug.print("Read would block!\n", .{});
file.waker.wait(.{ .read = true });
},
else => return err,
};
file.schedule(.{ .read = true });
return overlapped.InternalHigh;
}
const print = std.debug.print;
const assert = std.debug.assert;
fn loop(driver: *pike.Driver, stopped: *bool) callconv(.Async) !void {
defer stopped.* = true;
const address = try net.Address.parseIp("127.0.0.1", 9000);
var file = pike.File{ .driver = driver, .handle = try socket(address, os.SOCK_STREAM) };
defer close(@ptrCast(ws2_32.SOCKET, file.handle));
try driver.register(&file, .{ .read = true, .write = true });
try pike.os.setsockopt(file.handle, pike.os.SOL_SOCKET, pike.os.SO_REUSEADDR, &mem.toBytes(@as(c_int, 1)));
try pike.os.bind(file.handle, &address.any, address.getOsSockLen());
try pike.os.listen(file.handle, 128);
std.debug.print("Listening for clients on: {}\n", .{address});
var client = try accept(&file);
try driver.register(&client.file, .{ .read = true, .write = true });
std.debug.print("New client connected: {}\n", .{client.address});
var buf: [65536]u8 = undefined;
while (true) {
const n = try read(&client.file, &buf);
// std.debug.print("Got: {}", .{buf[0..n]});
}
}
pub fn main() !void {
var driver = try pike.Driver.init(.{});
defer driver.deinit();
_ = try windows.WSAStartup(2, 2);
defer windows.WSACleanup() catch {};
var stopped = false;
var frame = async loop(&driver, &stopped);
while (!stopped) {
try driver.poll(10000);
}
try nosuspend await frame;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment