Skip to content

Commit 454b4cc

Browse files
authored
Merge pull request #907 from devlights/add-tcp-reuseaddr-onoff-example
2 parents 8bfd2b0 + bee06a6 commit 454b4cc

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: run
9+
run:
10+
cmds:
11+
- go run . -listenconfig
12+
- go run .

examples/socket/tcp_reuseaddr/main.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
"log"
8+
"net"
9+
"syscall"
10+
)
11+
12+
type (
13+
Args struct {
14+
UseListenConfig bool
15+
}
16+
)
17+
18+
const (
19+
SO_REUSEADDR = syscall.SO_REUSEADDR
20+
SO_REUSEPORT = 0xf
21+
)
22+
23+
var (
24+
args Args
25+
)
26+
27+
func main() {
28+
log.SetFlags(log.Lmicroseconds)
29+
30+
flag.BoolVar(&args.UseListenConfig, "listenconfig", false, "Use net.ListenConfig")
31+
flag.Parse()
32+
33+
if err := run(); err != nil {
34+
panic(err)
35+
}
36+
}
37+
38+
func run() error {
39+
var err error
40+
switch args.UseListenConfig {
41+
case true:
42+
err = runListenConfig()
43+
default:
44+
err = runNormal()
45+
}
46+
47+
if err != nil {
48+
return err
49+
}
50+
51+
return nil
52+
}
53+
54+
func runListenConfig() error {
55+
lc := net.ListenConfig{
56+
Control: func(network, address string, c syscall.RawConn) error {
57+
var (
58+
reuseAddr, reusePort int
59+
opErr1, opErr2 error
60+
err error
61+
)
62+
63+
err = c.Control(func(fd uintptr) {
64+
reuseAddr, opErr1 = syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEADDR)
65+
reusePort, opErr2 = syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEPORT)
66+
})
67+
68+
if err != nil {
69+
return err
70+
}
71+
72+
log.Printf("SO_REUSEADDR=%d", reuseAddr)
73+
log.Printf("SO_REUSEPORT=%d", reusePort)
74+
75+
if opErr1 != nil {
76+
return opErr1
77+
}
78+
79+
if opErr2 != nil {
80+
return opErr2
81+
}
82+
83+
return nil
84+
},
85+
}
86+
87+
ln, err := lc.Listen(context.Background(), "tcp", ":8888")
88+
if err != nil {
89+
return err
90+
}
91+
defer ln.Close()
92+
93+
return nil
94+
}
95+
96+
func runNormal() error {
97+
ln, err := net.Listen("tcp", ":8888")
98+
if err != nil {
99+
return err
100+
}
101+
defer ln.Close()
102+
103+
tcpLn, ok := ln.(*net.TCPListener)
104+
if !ok {
105+
return fmt.Errorf("not a TCP Listener")
106+
}
107+
108+
file, err := tcpLn.File()
109+
if err != nil {
110+
return err
111+
}
112+
defer file.Close()
113+
114+
var (
115+
fd = file.Fd()
116+
v int
117+
)
118+
v, err = syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEADDR)
119+
if err != nil {
120+
return err
121+
}
122+
log.Printf("SO_REUSEADDR=%d", v)
123+
124+
v, err = syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEPORT)
125+
if err != nil {
126+
return err
127+
}
128+
log.Printf("SO_REUSEPORT=%d", v)
129+
130+
return nil
131+
}

0 commit comments

Comments
 (0)