Skip to content

Commit eba256d

Browse files
authored
Merge pull request #819 from devlights/add-unix-socket-example
2 parents d8c1151 + fbcc9bf commit eba256d

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./bin
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: run
9+
fmt:
10+
cmds:
11+
- goimports -w .
12+
prepare:
13+
cmds:
14+
- mkdir -p bin
15+
build:
16+
deps: [ fmt ]
17+
cmds:
18+
- go build -o bin/server server/server.go
19+
- go build -o bin/client client/client.go
20+
run:
21+
deps: [ build ]
22+
cmds:
23+
- ./bin/server &
24+
- sleep 1
25+
- ./bin/client
26+
- sleep 1
27+
- pgrep server && pkill server
28+
ignore_error: true
29+
clean:
30+
cmds:
31+
- rm -rf ./bin
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//go:build linux
2+
3+
package main
4+
5+
import (
6+
"log"
7+
"net"
8+
9+
"golang.org/x/sys/unix"
10+
)
11+
12+
func init() {
13+
log.SetFlags(log.Lmicroseconds)
14+
}
15+
16+
func main() {
17+
if err := run(); err != nil {
18+
log.Fatal(err)
19+
}
20+
}
21+
22+
func run() error {
23+
var (
24+
sfd int
25+
err error
26+
)
27+
28+
sfd, err = unix.Socket(unix.AF_INET, unix.SOCK_STREAM, unix.IPPROTO_TCP)
29+
if err != nil {
30+
return err
31+
}
32+
defer func() {
33+
log.Println("[CLIENT] ソケットクローズ")
34+
unix.Close(sfd)
35+
}()
36+
37+
var (
38+
ip = net.ParseIP("127.0.0.1")
39+
ipv4 [4]byte
40+
41+
sAddr unix.Sockaddr
42+
)
43+
copy(ipv4[:], ip.To4())
44+
45+
sAddr = &unix.SockaddrInet4{Port: 8888, Addr: ipv4}
46+
err = unix.Connect(sfd, sAddr)
47+
if err != nil {
48+
return err
49+
}
50+
51+
//
52+
// Send
53+
//
54+
var (
55+
buf = make([]byte, 2048)
56+
msg = "helloworld"
57+
)
58+
copy(buf, []byte(msg))
59+
60+
err = unix.Send(sfd, buf[:len(msg)], 0)
61+
if err != nil {
62+
return err
63+
}
64+
65+
//
66+
// Recv
67+
//
68+
var (
69+
n int
70+
)
71+
clear(buf)
72+
73+
n, err = unix.Read(sfd, buf)
74+
if err != nil {
75+
return err
76+
}
77+
78+
log.Printf("[CLIENT] %s", buf[:n])
79+
80+
return nil
81+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//go:build linux
2+
3+
package main
4+
5+
import (
6+
"errors"
7+
"log"
8+
"net"
9+
10+
"golang.org/x/sys/unix"
11+
)
12+
13+
func init() {
14+
log.SetFlags(log.Lmicroseconds)
15+
}
16+
17+
func main() {
18+
if err := run(); err != nil {
19+
log.Fatal(err)
20+
}
21+
}
22+
23+
func run() error {
24+
//
25+
// Create
26+
//
27+
var (
28+
sfd int
29+
err error
30+
)
31+
32+
sfd, err = unix.Socket(unix.AF_INET, unix.SOCK_STREAM, unix.IPPROTO_TCP)
33+
if err != nil {
34+
return err
35+
}
36+
defer func() {
37+
log.Println("[SERVER] サーバーソケットクローズ")
38+
unix.Close(sfd)
39+
}()
40+
41+
//
42+
// Bind and Listen
43+
//
44+
var (
45+
ip = net.ParseIP("127.0.0.1")
46+
ipv4 [4]byte
47+
48+
sAddr unix.Sockaddr
49+
backLog = 2
50+
)
51+
copy(ipv4[:], ip.To4())
52+
53+
sAddr = &unix.SockaddrInet4{Port: 8888, Addr: ipv4}
54+
err = unix.Bind(sfd, sAddr)
55+
if err != nil {
56+
return err
57+
}
58+
59+
err = unix.Listen(sfd, backLog)
60+
if err != nil {
61+
return err
62+
}
63+
64+
//
65+
// Accept
66+
//
67+
var (
68+
cfd int
69+
cAddr unix.Sockaddr
70+
)
71+
72+
cfd, cAddr, err = unix.Accept(sfd)
73+
if err != nil {
74+
return err
75+
}
76+
defer func() {
77+
log.Println("[SERVER] パケット送受信用ソケットクローズ")
78+
unix.Close(cfd)
79+
}()
80+
81+
cAddrInet4 := cAddr.(*unix.SockaddrInet4)
82+
log.Printf("[SERVER] Connect from %v:%v", cAddrInet4.Addr, cAddrInet4.Port)
83+
84+
//
85+
// Recv
86+
//
87+
var (
88+
buf = make([]byte, 2048)
89+
n int
90+
)
91+
92+
n, err = unix.Read(cfd, buf)
93+
if err != nil {
94+
return err
95+
}
96+
97+
log.Printf("[SERVER] %s", string(buf[:n]))
98+
99+
//
100+
// Send
101+
//
102+
var (
103+
msg = "HELLOWORLD"
104+
)
105+
106+
clear(buf)
107+
copy(buf, []byte(msg))
108+
109+
err = unix.Send(cfd, buf[:len(msg)], 0)
110+
if err != nil {
111+
return err
112+
}
113+
114+
//
115+
// Disconnect detection
116+
//
117+
LOOP:
118+
for {
119+
clear(buf)
120+
121+
n, err = unix.Read(cfd, buf)
122+
switch {
123+
case n == 0:
124+
log.Println("[SERVER] 切断検知 (0 byte read)")
125+
break LOOP
126+
case err != nil:
127+
var sysErr unix.Errno
128+
if errors.As(err, &sysErr); sysErr == unix.ECONNRESET {
129+
log.Printf("[SERVER] 切断検知 (%s)", sysErr)
130+
break LOOP
131+
}
132+
}
133+
}
134+
135+
return nil
136+
}

0 commit comments

Comments
 (0)