Hi again Ziggit!
I’m currently working on a WebSocket project. I was able to create a simple socket connection, and even send an HTTP request to upgrade the connection to a WebSocket connection. My only question is, how do I send a websocket data frame to the websocket server? I looked around for help and found these:
I honestly don’t know how to code this at all in Zig, or let alone, any language as this is my first time doing anything networking related at this deep of a level. I would show the code I have tried, but I was being a script kiddie and used AI to tell me how to do this in C and I tried to translate it to Zig, but it didn’t end up working lol. Any explanations, examples, and hints would be greatly appreciated. And thank you again for always helping me out. I really appreciate you guys.
EDIT:
I decided to add my code in order to prevent confusion.
// client.zig
const std = @import("std");
const fmt = std.fmt;
const mem = std.mem;
const net = std.net;
const time = std.time;
const math = std.math;
const crypto = std.crypto;
const base64 = std.base64;
const random = std.Random;
const RequestUpgradeError = error{ NoResponse, UpgradeFailed };
const SERVER_IP = [4]u8{ 127, 0, 0, 1 };
const SERVER_PORT: u16 = 9001;
const WebSocket = struct {
stream: net.Stream,
pub fn recieveFrame(self: *WebSocket) !?[]u8 {
var buffer: [65535]u8 = undefined;
const body_index: usize = 134;
const msg_len = try self.stream.read(&buffer);
if (body_index < msg_len) {
return buffer[body_index..msg_len];
} else {
return null;
}
}
pub fn sendFrame(self: *WebSocket, msg: []const u8) !void {
// I need help here :(
}
};
const Client = struct {
allocator: std.mem.Allocator,
server_ip: [4]u8,
server_ip_str: []u8,
server_port: u16,
websocket_key: []u8,
stream: net.Stream,
pub fn requestUpgrade(self: *Client) !WebSocket {
const reader = self.stream.reader();
var rd_buf: [65535]u8 = undefined;
const http_payload_fmt = "GET / HTTP/1.1\r\n" ++
"Host: {s}:{d}\r\n" ++
"Upgrade: websocket\r\n" ++
"Connection: Upgrade\r\n" ++
"Sec-WebSocket-Key: {s}\r\n" ++
"Sec-WebSocket-Version: 13\r\n\r\n";
const req_upgrade = try fmt.allocPrint(self.allocator, http_payload_fmt, .{ self.server_ip_str, SERVER_PORT, self.websocket_key });
defer self.allocator.free(req_upgrade);
std.debug.print("[*] Sending WebSocket upgrade request to the server...\n", .{});
try self.stream.writeAll(req_upgrade);
const res_upgrade = try reader.readUntilDelimiterOrEof(&rd_buf, '\n') orelse return RequestUpgradeError.NoResponse;
const successful_res = "HTTP/1.1 101 Switching Protocols\r";
if (mem.eql(u8, res_upgrade, successful_res) == false) return RequestUpgradeError.UpgradeFailed;
std.debug.print("[*] Session successfully upgraded to a WebSocket connection...\n\n", .{});
return .{ .stream = self.stream };
}
pub fn init(allocator: std.mem.Allocator, ip: [4]u8, port: u16, server_ip_str: []u8, websoc_key: []u8, stream: net.Stream) Client {
return .{ .allocator = allocator, .server_ip = ip, .server_port = port, .server_ip_str = server_ip_str, .websocket_key = websoc_key, .stream = stream };
}
pub fn deinit(self: *Client) void {
self.stream.close();
self.allocator.free(self.server_ip_str);
self.allocator.free(self.websocket_key);
}
};
// server.ts
console.log("Running WebSocket server!");
Bun.serve({
fetch(req, server) {
console.log(req);
if(server.upgrade(req)) {
return;
}
return new Response("Upgrade failed", { status: 500 });
},
websocket: {
open(ws) {
console.log("Connection opened!");
ws.send("Howdy :) welcome to the server!");
},
message(ws, message) {
console.log("Message recieved!");
ws.send("Thanks for your message :)");
},
close(ws, code, reason) {
console.log("Session closed");
},
},
port: 9001,
});