Created
October 6, 2020 14:56
-
-
Save lithdew/eb3e1372573c33430a022e2e69b56e33 to your computer and use it in GitHub Desktop.
pike (windows): benchmark tcp client and server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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