TCP client hangs while writing to server

I have two pieces, that work:
Server

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}).init;
    const allocator = blk: {
        const builtin = @import("builtin");
        break :blk switch (builtin.mode) {
            .ReleaseFast => std.heap.smp_allocator,
            else => gpa.allocator(),
        };
    };
    _ = &allocator;

    const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
    var server = try address.listen(.{
        .reuse_address = true,
    });
    defer server.deinit();
    log.info("Server started on address: {}!", .{address});

    var close: bool = false;
    while (!close) {
        const connection = try server.accept();
        var stream = connection.stream;
        defer stream.close();

        const action = try stream.reader().readInt(
            u16,
            .little,
        );

        switch (action) {
            0 => {
                log.debug("action: {d}", .{action});
                if (action == 0) {
                    close = true;
                    continue;
                }
            },
            2 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch unreachable;

                const res: bool = lib.robot_is_inited(
                    p0,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch unreachable;
            },
            // <Other actions>
            else => {
                log.warn("Unhandled action: {d}", .{action});
            },
        }
    }
    log.info("Closeing...", .{});
}

Client (action = 2)

    ... other actions ...

    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
    const stream = std.net.tcpConnectToAddress(address) catch unreachable;

    _ = stream.writer().writeInt(u16, 2, .little) catch unreachable;
    _ = stream.writer().writeInt(usize, p0, .little) catch unreachable;
    _ = stream.writeAll("") catch unreachable;

    const res = read_block: {var read_buf: [1]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(bool, &read_buf);} catch unreachable;
    return res;

    ... other actions ...

Sometimes, when connection is initiated, server hangs on server.accept(), but client already tries to write. So connection will be hang for some time, before timeout. Is there something that I can do, to ensure that connection was opened? And also I’ve thought to make timeout smaller, but I don’t know how.
P.S.: Also, may be someone would came with better idea, how to pass data. This is middleware + server to debug dll, while it’s connected to program, that actively defends against debuggers. I wanted to write program on zig, but not on their C-like language with proprietary compiler and debuger. So shared libraries were made.
P.P.S.: It’s auto generated in comptime from actual set of functions, and there are 22 actions. As I can see from different tests, the problem accrued on each of 22 actions, and after different amount of requests (2k-3k). So I’m thinking that some bad tcp packet is ruining my debug session.

1 Like

I’d like to help but I don’t see whole picture
Could you please share repo url?

Also It is not clear whether you have two processes(client/server) or the same main contain both and works according to command line arguments

BTW - TCP Server in Zig - Part 1 - Single Threaded - series of great articles about Zig networking

Special attention- REUSEADDR

2 Likes

I can share generated client and server to call library. Server and middleware are different processes.

Server (separate process)
const lib = @import("mql5_trading");
const std = @import("std");
const posix = std.posix;
pub const std_options: std.Options = .{
    .log_level = .debug,
};
const log = std.log.scoped(.zig_mql_server);

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}).init;
    const allocator = blk: {
        const builtin = @import("builtin");
        break :blk switch (builtin.mode) {
            .ReleaseFast => std.heap.smp_allocator,
            else => gpa.allocator(),
        };
    };
    _ = &allocator;

    const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
    var server = try address.listen(.{
        .reuse_address = true,
    });
    defer server.deinit();
    log.info("Server started on address: {}!", .{address});

    var close: bool = false;
    while (!close) {
        const connection = server.accept() catch continue;
        var stream = connection.stream;
        defer stream.close();

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &std.mem.toBytes(timeout)) catch continue;
        // posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        const action = stream.reader().readInt(
            u16,
            .little,
        ) catch continue;

        switch (action) {
            0 => {
                log.debug("action: {d}", .{action});
                if (action == 0) {
                    close = true;
                    continue;
                }
            },
            2 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: bool = lib.robot_is_inited(
                    p0,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            3 => {
                const res: usize = lib.robot_init(
                );
                _ = stream.writer().writeInt(usize, res, .little) catch continue;
            },
            4 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: void = lib.robot_deinit(
                    p0,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            5 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: i32 = lib.robot_signal(
                    p0,
                );
                _ = stream.writer().writeInt(i32, res, .little) catch continue;
            },
            6 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: f64 = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;

                const p2: f64 = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;

                const p3: f64 = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;

                const p4: f64 = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;

                const p5: f64 = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;

                const res: void = lib.robot_update_context(
                    p0,
                    p1,
                    p2,
                    p3,
                    p4,
                    p5,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            7 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: usize = stream.reader().readInt(usize, .little) catch continue;

                const p2_len = stream.reader().readInt(usize, .little) catch continue;
                const p2: []lib.OrderMQL5 = allocator.alloc(lib.OrderMQL5, p2_len) catch continue;
                defer allocator.free(p2);
                for (p2) |*p2_sub| {
                    p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
                }
                const p3: lib.OrderTypeMQL5 = stream.reader().readEnum(lib.OrderTypeMQL5, .little) catch continue;

                const p4: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: isize = lib.robot_order_closer(
                    p0,
                    p1,
                    p2.ptr,
                    p3,
                    p4,
                );
                _ = stream.writer().writeInt(usize, p2_len, .little) catch continue;
                for (p2[0..p2_len]) |p2_sub| {
                    _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
                }
                _ = stream.writer().writeInt(isize, res, .little) catch continue;
            },
            8 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: usize = stream.reader().readInt(usize, .little) catch continue;

                const p2_len = stream.reader().readInt(usize, .little) catch continue;
                const p2: []lib.OrderMQL5 = allocator.alloc(lib.OrderMQL5, p2_len) catch continue;
                defer allocator.free(p2);
                for (p2) |*p2_sub| {
                    p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
                }
                const p3: lib.OrderTypeMQL5 = stream.reader().readEnum(lib.OrderTypeMQL5, .little) catch continue;

                const p4: usize = stream.reader().readInt(usize, .little) catch continue;

                const p5: usize = stream.reader().readInt(usize, .little) catch continue;

                const p6_len = stream.reader().readInt(usize, .little) catch continue;
                const p6: []lib.OrderMQL5 = allocator.alloc(lib.OrderMQL5, p6_len) catch continue;
                defer allocator.free(p6);
                for (p6) |*p6_sub| {
                    p6_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
                }
                const p7: lib.OrderTypeMQL5 = stream.reader().readEnum(lib.OrderTypeMQL5, .little) catch continue;

                const p8: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: bool = lib.robot_trall(
                    p0,
                    p1,
                    p2.ptr,
                    p3,
                    p4,
                    p5,
                    p6.ptr,
                    p7,
                    p8,
                );
                _ = stream.writer().writeInt(usize, p2_len, .little) catch continue;
                for (p2[0..p2_len]) |p2_sub| {
                    _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
                }
                _ = stream.writer().writeInt(usize, p6_len, .little) catch continue;
                for (p6[0..p6_len]) |p6_sub| {
                    _ = stream.writer().writeStructEndian(p6_sub, .little) catch continue;
                }
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            9 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: i32 = lib.robot_tier(
                    p0,
                );
                _ = stream.writer().writeInt(i32, res, .little) catch continue;
            },
            10 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: usize = stream.reader().readInt(usize, .little) catch continue;

                const p2_len = stream.reader().readInt(usize, .little) catch continue;
                const p2: []lib.OrderMQL5 = allocator.alloc(lib.OrderMQL5, p2_len) catch continue;
                defer allocator.free(p2);
                for (p2) |*p2_sub| {
                    p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
                }
                const p3: lib.OrderTypeMQL5 = stream.reader().readEnum(lib.OrderTypeMQL5, .little) catch continue;

                const p4: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: f64 = lib.robot_averaging_next_price(
                    p0,
                    p1,
                    p2.ptr,
                    p3,
                    p4,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            11 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: usize = stream.reader().readInt(usize, .little) catch continue;

                const p2_len = stream.reader().readInt(usize, .little) catch continue;
                const p2: []lib.OrderMQL5 = allocator.alloc(lib.OrderMQL5, p2_len) catch continue;
                defer allocator.free(p2);
                for (p2) |*p2_sub| {
                    p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
                }
                const p3: lib.OrderTypeMQL5 = stream.reader().readEnum(lib.OrderTypeMQL5, .little) catch continue;

                const p4: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: bool = lib.robot_trending_check(
                    p0,
                    p1,
                    p2.ptr,
                    p3,
                    p4,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            12 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: lib.IndicatorTagMQL = stream.reader().readEnum(lib.IndicatorTagMQL, .little) catch continue;

                var p2: lib.IndicatorMQL = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(lib.IndicatorMQL, &read_buf);} catch continue;

                const res: void = lib.robot_set_indicator(
                    p0,
                    p1,
                    &p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            13 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: lib.OrderCloserTagMQL = stream.reader().readEnum(lib.OrderCloserTagMQL, .little) catch continue;

                var p2: lib.OrderCloserMQL = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(lib.OrderCloserMQL, &read_buf);} catch continue;

                const res: void = lib.robot_set_order_closer(
                    p0,
                    p1,
                    &p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            14 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: lib.TrallTagMQL = stream.reader().readEnum(lib.TrallTagMQL, .little) catch continue;

                var p2: lib.TrallMQL = read_block: {var read_buf: [40]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(lib.TrallMQL, &read_buf);} catch continue;

                const res: void = lib.robot_set_trall(
                    p0,
                    p1,
                    &p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            15 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1_len = stream.reader().readInt(usize, .little) catch continue;
                const p1: []usize = allocator.alloc(usize, p1_len) catch continue;
                defer allocator.free(p1);
                for (p1) |*p1_sub| {
                    p1_sub.* = stream.reader().readInt(usize, .little) catch continue;
                }
                const p2_len = stream.reader().readInt(usize, .little) catch continue;
                const p2: []f64 = allocator.alloc(f64, p2_len) catch continue;
                defer allocator.free(p2);
                for (p2) |*p2_sub| {
                    p2_sub.* = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;
                }
                const p3: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: void = lib.robot_set_tiering_quantile(
                    p0,
                    p1.ptr,
                    p2.ptr,
                    p3,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            16 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1_len = stream.reader().readInt(usize, .little) catch continue;
                const p1: []usize = allocator.alloc(usize, p1_len) catch continue;
                defer allocator.free(p1);
                for (p1) |*p1_sub| {
                    p1_sub.* = stream.reader().readInt(usize, .little) catch continue;
                }
                const p2: usize = stream.reader().readInt(usize, .little) catch continue;

                const p3: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: void = lib.robot_set_tiering_minmax(
                    p0,
                    p1.ptr,
                    p2,
                    p3,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            17 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1_len = stream.reader().readInt(usize, .little) catch continue;
                const p1: []usize = allocator.alloc(usize, p1_len) catch continue;
                defer allocator.free(p1);
                for (p1) |*p1_sub| {
                    p1_sub.* = stream.reader().readInt(usize, .little) catch continue;
                }
                const p2: usize = stream.reader().readInt(usize, .little) catch continue;

                const p3: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: void = lib.robot_set_tiering_trend(
                    p0,
                    p1.ptr,
                    p2,
                    p3,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            18 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: lib.AveragingTagMQL = stream.reader().readEnum(lib.AveragingTagMQL, .little) catch continue;

                var p2: lib.AveragingMQL = read_block: {var read_buf: [12]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(lib.AveragingMQL, &read_buf);} catch continue;

                const res: void = lib.robot_set_averaging(
                    p0,
                    p1,
                    &p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            19 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1: lib.TrendingTagMQL = stream.reader().readEnum(lib.TrendingTagMQL, .little) catch continue;

                var p2: lib.TrendingMQL = read_block: {var read_buf: [16]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(lib.TrendingMQL, &read_buf);} catch continue;

                const res: void = lib.robot_set_trending(
                    p0,
                    p1,
                    &p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            20 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                const p1_len = stream.reader().readInt(usize, .little) catch continue;
                const p1: []lib.BarMQL5 = allocator.alloc(lib.BarMQL5, p1_len) catch continue;
                defer allocator.free(p1);
                for (p1) |*p1_sub| {
                    p1_sub.* = stream.reader().readStructEndian(lib.BarMQL5, .little) catch continue;
                }
                const p2: usize = stream.reader().readInt(usize, .little) catch continue;

                const res: void = lib.robot_bars_populate(
                    p0,
                    p1.ptr,
                    p2,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            21 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                var p1: lib.BarMQL5 = stream.reader().readStructEndian(lib.BarMQL5, .little) catch continue;

                const res: void = lib.robot_bar_update_last(
                    p0,
                    &p1,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },
            22 => {
                const p0: usize = stream.reader().readInt(usize, .little) catch continue;

                var p1: lib.BarMQL5 = stream.reader().readStructEndian(lib.BarMQL5, .little) catch continue;

                const res: void = lib.robot_bar_push(
                    p0,
                    &p1,
                );
                _ = stream.write(&std.mem.toBytes(res)) catch continue;
            },

            else => {
                log.warn("Unhandled action: {d}", .{action});
            },
        }
    }
    log.info("Closeing...", .{});
}

The part that inside the library is working properly, since while i’m turning off middleware (connectng library straight), all dll calls are performed exactly as expected.
I’ve added timeout and it helped a little bit. At the begining middleware is sending few hundreds requests per second and after some time, server stops accepting connections properly.

Middleware (plugin in form of shared library)
const lib = @import("mql5_trading");
const std = @import("std");
const posix = std.posix;

pub export fn robot_is_inited(
    p0: usize,
) callconv(.C) bool {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 2, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [1]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(bool, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_init(
) callconv(.C) usize {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 3, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = stream.reader().readInt(usize, .little) catch continue;
        return res;
    }
}
pub export fn robot_deinit(
    p0: usize,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 4, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_signal(
    p0: usize,
) callconv(.C) i32 {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 5, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = stream.reader().readInt(i32, .little) catch continue;
        return res;
    }
}
pub export fn robot_update_context(
    p0: usize,
    p1: f64,
    p2: f64,
    p3: f64,
    p4: f64,
    p5: f64,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 6, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2)) catch continue;
        _ = stream.write(&std.mem.toBytes(p3)) catch continue;
        _ = stream.write(&std.mem.toBytes(p4)) catch continue;
        _ = stream.write(&std.mem.toBytes(p5)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_order_closer(
    p0: usize,
    p1: usize,
    p2: [*]lib.OrderMQL5,
    p3: lib.OrderTypeMQL5,
    p4: usize,
) callconv(.C) isize {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 7, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p1, .little) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        for (p2[0..p4]) |p2_sub| {
            _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
        }
        _ = stream.write(&std.mem.toBytes(p3)) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const p2_len = stream.reader().readInt(usize, .little) catch continue;
        for (p2[0..p2_len]) |*p2_sub| {
            p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
        }
        const res = stream.reader().readInt(isize, .little) catch continue;
        return res;
    }
}
pub export fn robot_trall(
    p0: usize,
    p1: usize,
    p2: [*]lib.OrderMQL5,
    p3: lib.OrderTypeMQL5,
    p4: usize,
    p5: usize,
    p6: [*]lib.OrderMQL5,
    p7: lib.OrderTypeMQL5,
    p8: usize,
) callconv(.C) bool {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 8, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p1, .little) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        for (p2[0..p4]) |p2_sub| {
            _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
        }
        _ = stream.write(&std.mem.toBytes(p3)) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        _ = stream.writer().writeInt(usize, p5, .little) catch continue;
        _ = stream.writer().writeInt(usize, p8, .little) catch continue;
        for (p6[0..p8]) |p6_sub| {
            _ = stream.writer().writeStructEndian(p6_sub, .little) catch continue;
        }
        _ = stream.write(&std.mem.toBytes(p7)) catch continue;
        _ = stream.writer().writeInt(usize, p8, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const p2_len = stream.reader().readInt(usize, .little) catch continue;
        for (p2[0..p2_len]) |*p2_sub| {
            p2_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
        }
        const p6_len = stream.reader().readInt(usize, .little) catch continue;
        for (p6[0..p6_len]) |*p6_sub| {
            p6_sub.* = stream.reader().readStructEndian(lib.OrderMQL5, .little) catch continue;
        }
        const res = read_block: {var read_buf: [1]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(bool, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_tier(
    p0: usize,
) callconv(.C) i32 {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 9, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = stream.reader().readInt(i32, .little) catch continue;
        return res;
    }
}
pub export fn robot_averaging_next_price(
    p0: usize,
    p1: usize,
    p2: [*]const lib.OrderMQL5,
    p3: lib.OrderTypeMQL5,
    p4: usize,
) callconv(.C) f64 {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 10, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p1, .little) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        for (p2[0..p4]) |p2_sub| {
            _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
        }
        _ = stream.write(&std.mem.toBytes(p3)) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [8]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(f64, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_trending_check(
    p0: usize,
    p1: usize,
    p2: [*]const lib.OrderMQL5,
    p3: lib.OrderTypeMQL5,
    p4: usize,
) callconv(.C) bool {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 11, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p1, .little) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        for (p2[0..p4]) |p2_sub| {
            _ = stream.writer().writeStructEndian(p2_sub, .little) catch continue;
        }
        _ = stream.write(&std.mem.toBytes(p3)) catch continue;
        _ = stream.writer().writeInt(usize, p4, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [1]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(bool, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_indicator(
    p0: usize,
    p1: lib.IndicatorTagMQL,
    p2: *const lib.IndicatorMQL,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 12, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2.*)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_order_closer(
    p0: usize,
    p1: lib.OrderCloserTagMQL,
    p2: *const lib.OrderCloserMQL,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 13, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2.*)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_trall(
    p0: usize,
    p1: lib.TrallTagMQL,
    p2: *const lib.TrallMQL,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 14, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2.*)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_tiering_quantile(
    p0: usize,
    p1: [*]const usize,
    p2: [*]const f64,
    p3: usize,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 15, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p3, .little) catch continue;
        for (p1[0..p3]) |p1_sub| {
            _ = stream.writer().writeInt(usize, p1_sub, .little) catch continue;
        }
        _ = stream.writer().writeInt(usize, p3, .little) catch continue;
        for (p2[0..p3]) |p2_sub| {
            _ = stream.write(&std.mem.toBytes(p2_sub)) catch continue;
        }
        _ = stream.writer().writeInt(usize, p3, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_tiering_minmax(
    p0: usize,
    p1: [*]const usize,
    p2: usize,
    p3: usize,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 16, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        for (p1[0..p2]) |p1_sub| {
            _ = stream.writer().writeInt(usize, p1_sub, .little) catch continue;
        }
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        _ = stream.writer().writeInt(usize, p3, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_tiering_trend(
    p0: usize,
    p1: [*]const usize,
    p2: usize,
    p3: usize,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 17, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        for (p1[0..p2]) |p1_sub| {
            _ = stream.writer().writeInt(usize, p1_sub, .little) catch continue;
        }
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        _ = stream.writer().writeInt(usize, p3, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_averaging(
    p0: usize,
    p1: lib.AveragingTagMQL,
    p2: *const lib.AveragingMQL,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 18, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2.*)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_set_trending(
    p0: usize,
    p1: lib.TrendingTagMQL,
    p2: *const lib.TrendingMQL,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 19, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.write(&std.mem.toBytes(p1)) catch continue;
        _ = stream.write(&std.mem.toBytes(p2.*)) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_bars_populate(
    p0: usize,
    p1: [*]const lib.BarMQL5,
    p2: usize,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 20, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        for (p1[0..p2]) |p1_sub| {
            _ = stream.writer().writeStructEndian(p1_sub, .little) catch continue;
        }
        _ = stream.writer().writeInt(usize, p2, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_bar_update_last(
    p0: usize,
    p1: *const lib.BarMQL5,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 21, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeStructEndian(p1.*, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}
pub export fn robot_bar_push(
    p0: usize,
    p1: *const lib.BarMQL5,
) callconv(.C) void {
    var ca = std.heap.DebugAllocator(.{}){};
    defer _ = ca.deinit();

    while(true) {
        const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 59887);
        const stream = std.net.tcpConnectToAddress(address) catch continue;

        const timeout = posix.timeval{ .sec = 0, .usec = 500 };
        posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &std.mem.toBytes(timeout)) catch continue;

        _ = stream.writer().writeInt(u16, 22, .little) catch continue;
        _ = stream.writer().writeInt(usize, p0, .little) catch continue;
        _ = stream.writer().writeStructEndian(p1.*, .little) catch continue;
        _ = stream.writeAll("") catch continue;

        const res = read_block: {var read_buf: [0]u8 = undefined; _ = stream.reader().read(&read_buf) catch |e| {break :read_block e;}; break :read_block std.mem.bytesToValue(void, &read_buf);} catch continue;
        return res;
    }
}

Term shared library raised my attention: do you work on Windows?

If yes - check setsockopt RCVTIMEO does not work on Windows

1 Like

Some advice - step by step
Your first flow on the server side:

  • Listen
  • Accept connection
  • read N bytes
  • disconnect

On the client side:

  • Try Connect till success
  • Write N bytes
  • Disconnect

Don’t use endiannes functions, stright write/read

Pay attention that write should not write all bytes, actual written will be returned etc (or use writeAll)

When this flow will work stable - add functionality

1 Like

Also check accept() error:

pub const AcceptError = error{
    ConnectionAborted,

    /// The file descriptor sockfd does not refer to a socket.
    FileDescriptorNotASocket,

    /// The per-process limit on the number of open file descriptors has been reached.
    ProcessFdQuotaExceeded,

    /// The system-wide limit on the total number of open files has been reached.
    SystemFdQuotaExceeded,

    /// Not enough free memory.  This often means that the memory allocation  is  limited
    /// by the socket buffer limits, not by the system memory.
    SystemResources,

    /// Socket is not listening for new connections.
    SocketNotListening,

    ProtocolFailure,

    /// Firewall rules forbid connection.
    BlockedByFirewall,

    /// This error occurs when no global event loop is configured,
    /// and accepting from the socket would block.
    WouldBlock,

    /// An incoming connection was indicated, but was subsequently terminated by the
    /// remote peer prior to accepting the call.
    ConnectionResetByPeer,

    /// The network subsystem has failed.
    NetworkSubsystemFailed,

    /// The referenced socket is not a type that supports connection-oriented service.
    OperationNotSupported,
} || UnexpectedError;

Because your client for every command create connection, error from accept will show the problem - too many not closed connections

You can simply check it:

    pub const ListenOptions = struct {
        /// How many connections the kernel will accept on the application's behalf.
        /// If more than this many connections pool in the kernel, clients will start
        /// seeing "Connection refused".
        kernel_backlog: u31 = 128,
        /// Sets SO_REUSEADDR and SO_REUSEPORT on POSIX.
        /// Sets SO_REUSEADDR on Windows, which is roughly equivalent.
        reuse_address: bool = false,
        /// Deprecated. Does the same thing as reuse_address.
        reuse_port: bool = false,
        force_nonblocking: bool = false,
    };

set kernel_backlog to something small

1 Like

Yes, the problem were in the refused connections… I’ve solved it by extracting connection and just reusing it instead of opening new connections. Since both server and client are single-threaded, it was pretty easy. And it’s also increased performance. Since program don’t need to open new connection every time.
Thank you for help!

1 Like