https://github.com/Thomvanoorschot/async_zocket
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.
https://github.com/Thomvanoorschot/async_zocket
async eventloop libuv libxev non-blocking singlethread tcp-client websocket-client websocket-server websockets wss zig-package ziglang
Last synced: 7 months ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/Thomvanoorschot/async_zocket
- Owner: Thomvanoorschot
- License: mit
- Created: 2025-03-29T16:30:13.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-06-06T18:18:57.000Z (7 months ago)
- Last Synced: 2025-06-06T19:29:35.358Z (7 months ago)
- Topics: async, eventloop, libuv, libxev, non-blocking, singlethread, tcp-client, websocket-client, websocket-server, websockets, wss, zig-package, ziglang
- Language: Zig
- Homepage:
- Size: 1.35 MB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-zig - Thomvanoorschot/async_zocket - Async WebSocket library for Zig, able to run concurrently on a single thread. (Network / Large Language Model)
README
# 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`:
```zig
.dependencies = .{
.async_zocket = .{
.url = "https://github.com/thomvanoorschot/async_zocket/archive/main.tar.gz",
.hash = "...", // Update with actual hash
},
},
```
### Basic Client Usage
```zig
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",
},
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
```zig
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,
.{
.address = try std.net.Address.parseIp4("127.0.0.1", 8080),
.max_connections = 100,
},
@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
**ServerOptions:**
- `address: std.net.Address` - Server bind address
- `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
**Upcoming Features:**
- 🔄 Fragmented message support
- 🔄 SSL/TLS support (WSS)
## 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.