zig
                                
                                 zig copied to clipboard
                                
                                    zig copied to clipboard
                            
                            
                            
                        std.net.StreamServer does not support port reuse
Zig Version
0.9.1
Steps to Reproduce
- code main.zig:
const std = @import("std");
const StreamServer = std.net.StreamServer;
const Address = std.net.Address;
pub fn main() anyerror!void {
    var server = StreamServer.init(.{
        .reuse_address = true,
    });
    defer server.deinit();
    var addr = try Address.parseIp("127.0.0.1", 8080);
    try server.listen(addr);
    
    while (true) {
        //do sth.
        std.time.sleep(1*std.time.ns_per_s);
    }
    std.log.info("ok.", .{});
}
- build
zig build
- run
./zig-out/bin/streamServerPortReuse &
./zig-out/bin/streamServerPortReuse
Expected Behavior
Multiple instances can run without error.
StreamServer can accept reuse_port parameter.
const std = @import("std");
const StreamServer = std.net.StreamServer;
const Address = std.net.Address;
pub fn main() anyerror!void {
    var server = StreamServer.init(.{
        .reuse_address = true,
        .reuse_port = true,        // FIXME:
    });
    defer server.deinit();
    var addr = try Address.parseIp("127.0.0.1", 8080);
    try server.listen(addr);
    
    while (true) {
        //do sth.
        std.time.sleep(1*std.time.ns_per_s);
    }
    std.log.info("ok.", .{});
}
After patching /opt/homebrew/Cellar/zig/0.9.1/lib/zig/std/net.zig, it accepts reuse_port parameter and works as expected.
diff --git a/net.zig b/net.zig
index f564a9d..942a79b 100644
--- a/net.zig
+++ b/net.zig
@@ -1706,6 +1706,7 @@ pub const StreamServer = struct {
     /// Copied from `Options` on `init`.
     kernel_backlog: u31,
     reuse_address: bool,
+    reuse_port: bool,
 
     /// `undefined` until `listen` returns successfully.
     listen_address: Address,
@@ -1720,6 +1721,9 @@ pub const StreamServer = struct {
 
         /// Enable SO.REUSEADDR on the socket.
         reuse_address: bool = false,
+
+        /// Enable SO.REUSEPORT on the socket.
+        reuse_port: bool = false,
     };
 
     /// After this call succeeds, resources have been acquired and must
@@ -1729,6 +1733,7 @@ pub const StreamServer = struct {
             .sockfd = null,
             .kernel_backlog = options.kernel_backlog,
             .reuse_address = options.reuse_address,
+            .reuse_port = options.reuse_port,
             .listen_address = undefined,
         };
     }
@@ -1759,6 +1764,14 @@ pub const StreamServer = struct {
                 &mem.toBytes(@as(c_int, 1)),
             );
         }
+        if (self.reuse_port) {
+            try os.setsockopt(
+                sockfd,
+                os.SOL.SOCKET,
+                os.SO.REUSEPORT,
+                &mem.toBytes(@as(c_int, 1)),
+            );
+        }
 
         var socklen = address.getOsSockLen();
         try os.bind(sockfd, &address.any, socklen);
Actual Behavior
The first instance works, but the second instance fails.
aka@akadeMacBook-Pro streamServerPortReuse% ./zig-out/bin/streamServerPortReuse &
[1] 15826
aka@akadeMacBook-Pro streamServerPortReuse % 
aka@akadeMacBook-Pro streamServerPortReuse % ./zig-out/bin/streamServerPortReuse  
error: AddressInUse
/opt/homebrew/Cellar/zig/0.9.1/lib/zig/std/os.zig:3135:27: 0x10291c51b in std.os.bind (streamServerPortReuse)
            .ADDRINUSE => return error.AddressInUse,
                          ^
/opt/homebrew/Cellar/zig/0.9.1/lib/zig/std/net.zig:1764:9: 0x10291958b in std.net.StreamServer.listen (streamServerPortReuse)
        try os.bind(sockfd, &address.any, socklen);
        ^
/Users/aka/github/streamServerPortReuse/src/main.zig:13:5: 0x1029190a3 in main (streamServerPortReuse)
    try server.listen(addr);
    ^
cc @amirrezaask I think this is one of the issues you were facing in your Live Coding A Web Server in Zig video series.
And while you are here, kudos for doing that series. It is interesting seeing someone new to Zig just intuiting their way around.
@komuw I am not sure if this is the problem that I have, I am suspecting that in case of crashes my program does not stop listening but maybe this issue is also related. 😅 i wanted to write stuff in zig and since there wasn't much content online I said let's give it a try, thanks for your kindness, really appreciate it, I hope I can continue it with other projects as well