Skip to content

This repository contains a basic, non-blocking WebSocket client written in the Zig programming language. It leverages the xev event loop for asynchronous operations and is able to run non-blocking on a single thread.

License

Notifications You must be signed in to change notification settings

Thomvanoorschot/async_zocket

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project Logo

AsyncZocket

Overview

AsyncZocket is a comprehensive WebSocket library for the Zig programming language, providing both client and server implementations. Built on the xev event loop library for high-performance asynchronous I/O operations, it offers a robust foundation for real-time communication applications. The library supports the full WebSocket protocol (RFC 6455) and can handle multiple concurrent connections efficiently on a single thread.

Features

Core WebSocket Support

  • Full RFC 6455 Compliance: Complete implementation of the WebSocket protocol specification
  • Frame Types: Support for Text, Binary, Close, Ping, and Pong frames
  • Proper Masking: Client-side frame masking and server-side unmasking
  • Control Frame Handling: Automatic Ping/Pong responses and proper Close handshake

Client Implementation

  • Non-blocking Client: Asynchronous WebSocket client with connection queuing
  • Connection Management: Automatic reconnection and connection state tracking
  • Write Queuing: Buffers write operations before connection establishment
  • Flexible Configuration: Configurable host, port, and path parameters

Server Implementation

  • High-Performance Server: Multi-client server with configurable connection limits
  • Connection Pooling: Efficient management of concurrent client connections
  • Callback-Based API: Event-driven architecture with customizable handlers

Technical Features

  • Asynchronous I/O: Built entirely on xev for non-blocking operations
  • Memory Efficient: Smart buffer management and connection pooling
  • Single-Threaded: Efficient event-loop based concurrency model

Getting Started

Installation

Use fetch:

zig fetch --save https://github.com/Thomvanoorschot/async_zocket/archive/main.tar.gz

Or add AsyncZocket to your build.zig.zon:

.dependencies = .{
    .async_zocket = .{
        .url = "https://github.com/thomvanoorschot/async_zocket/archive/main.tar.gz",
        .hash = "...", // Update with actual hash
    },
},

Basic Client Usage

const std = @import("std");
const AsyncZocket = @import("async_zocket");
const xev = @import("xev");

// Initialize event loop
var loop = try xev.Loop.init(.{});
defer loop.deinit();

// Define message callback
const wrapperStruct = struct {
    const Self = @This();
    fn read_callback(context: *anyopaque, payload: []const u8) !void {
        // You can access the context by casting it to the correct type
        // const self = @as(*Self, @ptrCast(context));
        // self.read_callback(self.callback_context, payload);
        std.log.info("read_callback: {s}\n", .{payload});
        _ = context;
    }
};
var ws = wrapperStruct{};

// Create and connect client
var client = try AsyncZocket.Client.init(
    std.heap.page_allocator,
    &loop,
    .{
        .host = "127.0.0.1",
        .port = 8080,
        .path = "/ws",
        .use_tls = true
    },
    wrapperStruct.read_callback,
    @ptrCast(&ws)
);

try client.connect();

// Send a message
try client.write("Hello, WebSocket!");

// Run event loop
try loop.run(.until_done);

Basic Server Usage

const std = @import("std");
const AsyncZocket = @import("async_zocket");
const xev = @import("xev");

// Initialize event loop
var loop = try xev.Loop.init(.{});
defer loop.deinit();

// Define callbacks
const wrapperStruct = struct {
    const Self = @This();
    fn accept_callback(
        _: ?*anyopaque,
        _: *xev.Loop,
        _: *xev.Completion,
        cc: *ClientConnection,
    ) xev.CallbackAction {
        cc.read();
        return .rearm;
    }
    fn read_callback(
        context: ?*anyopaque,
        payload: []const u8,
    ) void {
        _ = context;
        std.log.info("read_callback: {s}", .{payload});
        std.heap.page_allocator.free(payload);
    }
};
var ws = wrapperStruct{};

// Create and start server
var server = try AsyncZocket.Server.init(
    std.heap.page_allocator,
    &loop,
    .{
        .host = "127.0.0.1",
        .port = 8081,
        .max_connections = 10,
    },
    @ptrCast(&ws),
    wrapperStruct.accept_callback,
    wrapperStruct.read_callback,
);

server.accept();

// Run event loop
try loop.run(.until_done);

API Reference

Client

  • Client.init() - Initialize a new WebSocket client
  • client.connect() - Connect to the WebSocket server
  • client.write() - Send a text message
  • client.read() - Start reading incoming messages
  • client.deinit() - Clean up client resources

Server

  • Server.init() - Initialize a new WebSocket server
  • server.accept() - Start accepting client connections
  • server.returnConnection() - Return a closed connection to the pool
  • server.deinit() - Clean up server resources

Configuration

ClientConfig:

  • host: []const u8 - Server hostname or IP address
  • port: u16 - Server port number
  • path: []const u8 - WebSocket endpoint path
  • use_tls: bool - Encrypts traffic

ServerOptions:

  • host: []const u8 - Server hostname or IP address
  • port: u16 - Server port number
  • max_connections: u31 - Maximum concurrent connections (default: 1024)

Project Status

🚀 Production Ready - The library implements a complete WebSocket solution with both client and server capabilities.

Implemented Features:

  • Full WebSocket protocol (RFC 6455) compliance
  • Client and server implementations
  • All frame types (Text, Binary, Control frames)
  • Proper masking and unmasking
  • Connection management and pooling
  • Asynchronous I/O with xev
  • SSL/TLS support

Requirements

  • Zig 0.15.0-dev or later

Contributing

Contributions are welcome! Please feel free to submit pull requests, report bugs, or suggest features.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

This repository contains a basic, non-blocking WebSocket client written in the Zig programming language. It leverages the xev event loop for asynchronous operations and is able to run non-blocking on a single thread.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages