Skip to content

Commit e90f93c

Browse files
authored
Merge pull request #894 from devlights/add-net-textproto-example
2 parents c141a1a + 60c6f7e commit e90f93c

File tree

4 files changed

+335
-0
lines changed

4 files changed

+335
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
app
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# net/textprotoのサンプル
2+
3+
[net/textproto](https://pkg.go.dev/net/textproto@go1.24.1) パッケージは、テキストプロトコルを扱う通信処理を処理しやすくするパッケージ。
4+
5+
> Package textproto implements generic support for text-based request/response protocols in the style of HTTP, NNTP, and SMTP.
6+
7+
> (textprotoパッケージは、HTTP、NNTP、SMTPスタイルのテキストベースのリクエスト/レスポンスプロトコルの汎用サポートを実装します。)
8+
9+
# 実行
10+
11+
先に「ターミナル2」を起動しておき、その後に「ターミナル1」を実行。
12+
13+
## ターミナル1
14+
15+
```sh
16+
$ task
17+
task: [build] go build -o app .
18+
task: [run] ./app -server &
19+
task: [run] sleep 1
20+
task: [run] ./app
21+
200 ようこそ! コマンド:GET, SET, QUIT
22+
< SET Hello World
23+
200 VALUE SET SUCCESSFULLY
24+
< GET Hello
25+
200 World
26+
< QUIT
27+
200 BYE
28+
```
29+
30+
## ターミナル2
31+
32+
```sh
33+
$ task watch
34+
task: [watch] sudo tcpdump -i lo -n 'tcp port 8888' -S -X
35+
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
36+
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
37+
09:16:24.913973 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [S], seq 3624143825, win 43690, options [mss 65495,sackOK,TS val 316896963 ecr 0,nop,wscale 7], length 0
38+
0x0000: 4500 003c f12b 4000 4006 4b8e 7f00 0001 E..<.+@.@.K.....
39+
0x0010: 7f00 0001 cf5a 22b8 d804 0bd1 0000 0000 .....Z".........
40+
0x0020: a002 aaaa fe30 0000 0204 ffd7 0402 080a .....0..........
41+
0x0030: 12e3 76c3 0000 0000 0103 0307 ..v.........
42+
09:16:24.913989 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [S.], seq 3473127062, ack 3624143826, win 43690, options [mss 65495,sackOK,TS val 316896963 ecr 316896963,nop,wscale 7], length 0
43+
0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001 E..<..@.@.<.....
44+
0x0010: 7f00 0001 22b8 cf5a cf03 b696 d804 0bd2 ...."..Z........
45+
0x0020: a012 aaaa fe30 0000 0204 ffd7 0402 080a .....0..........
46+
0x0030: 12e3 76c3 12e3 76c3 0103 0307 ..v...v.....
47+
09:16:24.913998 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [.], ack 3473127063, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
48+
0x0000: 4500 0034 f12c 4000 4006 4b95 7f00 0001 E..4.,@.@.K.....
49+
0x0010: 7f00 0001 cf5a 22b8 d804 0bd2 cf03 b697 .....Z".........
50+
0x0020: 8010 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
51+
0x0030: 12e3 76c3 ..v.
52+
09:16:24.914117 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [P.], seq 3473127063:3473127112, ack 3624143826, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 49
53+
0x0000: 4500 0065 abdc 4000 4006 90b4 7f00 0001 E..e..@.@.......
54+
0x0010: 7f00 0001 22b8 cf5a cf03 b697 d804 0bd2 ...."..Z........
55+
0x0020: 8018 0156 fe59 0000 0101 080a 12e3 76c3 ...V.Y........v.
56+
0x0030: 12e3 76c3 3230 3020 e382 88e3 8186 e381 ..v.200.........
57+
0x0040: 93e3 819d 2120 e382 b3e3 839e e383 b3e3 ....!...........
58+
0x0050: 8389 efbc 9a47 4554 2c20 5345 542c 2051 .....GET,.SET,.Q
59+
0x0060: 5549 540d 0a UIT..
60+
09:16:24.914128 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [.], ack 3473127112, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
61+
0x0000: 4500 0034 f12d 4000 4006 4b94 7f00 0001 E..4.-@.@.K.....
62+
0x0010: 7f00 0001 cf5a 22b8 d804 0bd2 cf03 b6c8 .....Z".........
63+
0x0020: 8010 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
64+
0x0030: 12e3 76c3 ..v.
65+
09:16:24.914203 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [P.], seq 3624143826:3624143843, ack 3473127112, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 17
66+
0x0000: 4500 0045 f12e 4000 4006 4b82 7f00 0001 E..E..@.@.K.....
67+
0x0010: 7f00 0001 cf5a 22b8 d804 0bd2 cf03 b6c8 .....Z".........
68+
0x0020: 8018 0156 fe39 0000 0101 080a 12e3 76c3 ...V.9........v.
69+
0x0030: 12e3 76c3 5345 5420 4865 6c6c 6f20 576f ..v.SET.Hello.Wo
70+
0x0040: 726c 640d 0a rld..
71+
09:16:24.914212 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [.], ack 3624143843, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
72+
0x0000: 4500 0034 abdd 4000 4006 90e4 7f00 0001 E..4..@.@.......
73+
0x0010: 7f00 0001 22b8 cf5a cf03 b6c8 d804 0be3 ...."..Z........
74+
0x0020: 8010 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
75+
0x0030: 12e3 76c3 ..v.
76+
09:16:24.914248 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [P.], seq 3473127112:3473127140, ack 3624143843, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 28
77+
0x0000: 4500 0050 abde 4000 4006 90c7 7f00 0001 E..P..@.@.......
78+
0x0010: 7f00 0001 22b8 cf5a cf03 b6c8 d804 0be3 ...."..Z........
79+
0x0020: 8018 0156 fe44 0000 0101 080a 12e3 76c3 ...V.D........v.
80+
0x0030: 12e3 76c3 3230 3020 5641 4c55 4520 5345 ..v.200.VALUE.SE
81+
0x0040: 5420 5355 4343 4553 5346 554c 4c59 0d0a T.SUCCESSFULLY..
82+
09:16:24.914285 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [P.], seq 3624143843:3624143854, ack 3473127140, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 11
83+
0x0000: 4500 003f f12f 4000 4006 4b87 7f00 0001 E..?./@.@.K.....
84+
0x0010: 7f00 0001 cf5a 22b8 d804 0be3 cf03 b6e4 .....Z".........
85+
0x0020: 8018 0156 fe33 0000 0101 080a 12e3 76c3 ...V.3........v.
86+
0x0030: 12e3 76c3 4745 5420 4865 6c6c 6f0d 0a ..v.GET.Hello..
87+
09:16:24.914327 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [P.], seq 3473127140:3473127151, ack 3624143854, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 11
88+
0x0000: 4500 003f abdf 4000 4006 90d7 7f00 0001 E..?..@.@.......
89+
0x0010: 7f00 0001 22b8 cf5a cf03 b6e4 d804 0bee ...."..Z........
90+
0x0020: 8018 0156 fe33 0000 0101 080a 12e3 76c3 ...V.3........v.
91+
0x0030: 12e3 76c3 3230 3020 576f 726c 640d 0a ..v.200.World..
92+
09:16:24.914360 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [P.], seq 3624143854:3624143860, ack 3473127151, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 6
93+
0x0000: 4500 003a f130 4000 4006 4b8b 7f00 0001 E..:.0@.@.K.....
94+
0x0010: 7f00 0001 cf5a 22b8 d804 0bee cf03 b6ef .....Z".........
95+
0x0020: 8018 0156 fe2e 0000 0101 080a 12e3 76c3 ...V..........v.
96+
0x0030: 12e3 76c3 5155 4954 0d0a ..v.QUIT..
97+
09:16:24.914391 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [P.], seq 3473127151:3473127160, ack 3624143860, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 9
98+
0x0000: 4500 003d abe0 4000 4006 90d8 7f00 0001 E..=..@.@.......
99+
0x0010: 7f00 0001 22b8 cf5a cf03 b6ef d804 0bf4 ...."..Z........
100+
0x0020: 8018 0156 fe31 0000 0101 080a 12e3 76c3 ...V.1........v.
101+
0x0030: 12e3 76c3 3230 3020 4259 450d 0a ..v.200.BYE..
102+
09:16:24.914412 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [F.], seq 3473127160, ack 3624143860, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
103+
0x0000: 4500 0034 abe1 4000 4006 90e0 7f00 0001 E..4..@.@.......
104+
0x0010: 7f00 0001 22b8 cf5a cf03 b6f8 d804 0bf4 ...."..Z........
105+
0x0020: 8011 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
106+
0x0030: 12e3 76c3 ..v.
107+
09:16:24.914427 IP 127.0.0.1.53082 > 127.0.0.1.8888: Flags [F.], seq 3624143860, ack 3473127161, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
108+
0x0000: 4500 0034 f131 4000 4006 4b90 7f00 0001 E..4.1@.@.K.....
109+
0x0010: 7f00 0001 cf5a 22b8 d804 0bf4 cf03 b6f9 .....Z".........
110+
0x0020: 8011 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
111+
0x0030: 12e3 76c3 ..v.
112+
09:16:24.914440 IP 127.0.0.1.8888 > 127.0.0.1.53082: Flags [.], ack 3624143861, win 342, options [nop,nop,TS val 316896963 ecr 316896963], length 0
113+
0x0000: 4500 0034 abe2 4000 4006 90df 7f00 0001 E..4..@.@.......
114+
0x0010: 7f00 0001 22b8 cf5a cf03 b6f9 d804 0bf5 ...."..Z........
115+
0x0020: 8010 0156 fe28 0000 0101 080a 12e3 76c3 ...V.(........v.
116+
0x0030: 12e3 76c3 ..v.
117+
^C
118+
15 packets captured
119+
30 packets received by filter
120+
0 packets dropped by kernel
121+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# https://taskfile.dev
2+
3+
version: "3"
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: build
9+
- task: run
10+
build:
11+
cmds:
12+
- go build -o app .
13+
run:
14+
cmds:
15+
- ./app -server &
16+
- sleep 1
17+
- ./app
18+
watch:
19+
cmds:
20+
- cmd: sudo tcpdump -i lo -n 'tcp port 8888' -S -X
21+
interactive: true
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
net/textproto パッケージのサンプルです。
3+
*/
4+
package main
5+
6+
import (
7+
"flag"
8+
"fmt"
9+
"net"
10+
"net/textproto"
11+
"strings"
12+
)
13+
14+
type (
15+
Args struct {
16+
IsServer bool
17+
}
18+
)
19+
20+
const (
21+
OK = 200
22+
NG = 400
23+
24+
CmdGet = "GET"
25+
CmdSet = "SET"
26+
CmdQuit = "QUIT"
27+
)
28+
29+
var (
30+
args Args
31+
)
32+
33+
func init() {
34+
flag.BoolVar(&args.IsServer, "server", false, "server mode")
35+
}
36+
37+
func main() {
38+
flag.Parse()
39+
40+
if err := run(); err != nil {
41+
panic(err)
42+
}
43+
}
44+
45+
func run() error {
46+
var err error
47+
48+
if args.IsServer {
49+
err = runServer()
50+
} else {
51+
err = runClient()
52+
}
53+
54+
if err != nil {
55+
return err
56+
}
57+
58+
return nil
59+
}
60+
61+
func runServer() error {
62+
l, err := net.Listen("tcp", ":8888")
63+
if err != nil {
64+
return err
65+
}
66+
defer l.Close()
67+
68+
// サンプルなので1回だけ受付
69+
// クライアントからは
70+
// - SET
71+
// - GET
72+
// - QUIT
73+
// の3コマンドのシーケンスが来るとする
74+
conn, err := l.Accept()
75+
if err != nil {
76+
return err
77+
}
78+
defer conn.Close()
79+
80+
// net/textprotoの接続として処理
81+
tpConn := textproto.NewConn(conn)
82+
defer tpConn.Close()
83+
84+
// ウェルカムメッセージ
85+
err = tpConn.PrintfLine("%d %s", OK, "ようこそ! コマンド: GET, SET, QUIT")
86+
if err != nil {
87+
return err
88+
}
89+
90+
// コマンド処理
91+
data := make(map[string]string)
92+
for {
93+
line, err := tpConn.ReadLine()
94+
if err != nil {
95+
return err
96+
}
97+
98+
parts := strings.Fields(line)
99+
if len(parts) == 0 {
100+
tpConn.PrintfLine("%d %s", NG, "コマンドが読み取れません")
101+
continue
102+
}
103+
104+
command := strings.ToUpper(parts[0])
105+
cmdArgs := parts[1:]
106+
107+
switch command {
108+
case CmdGet:
109+
if v, ok := data[cmdArgs[0]]; ok {
110+
tpConn.PrintfLine("%d %s", OK, v)
111+
} else {
112+
tpConn.PrintfLine("%d %s", NG, "KEY NOT FOUND")
113+
}
114+
case CmdSet:
115+
data[cmdArgs[0]] = cmdArgs[1]
116+
tpConn.PrintfLine("%d %s", OK, "VALUE SET SUCCESSFULLY")
117+
case CmdQuit:
118+
tpConn.PrintfLine("%d %s", OK, "BYE")
119+
return nil
120+
default:
121+
tpConn.PrintfLine("%d %s", NG, "UNKNOWN COMMAND")
122+
}
123+
}
124+
}
125+
126+
func runClient() error {
127+
conn, err := net.Dial("tcp", ":8888")
128+
if err != nil {
129+
return err
130+
}
131+
defer conn.Close()
132+
133+
tpConn := textproto.NewConn(conn)
134+
defer tpConn.Close()
135+
136+
code, message, err := tpConn.ReadCodeLine(OK)
137+
if err != nil {
138+
return err
139+
}
140+
141+
fmt.Printf("%d %s\n", code, message)
142+
143+
// SET
144+
m := fmt.Sprintf("%s %s %s", CmdSet, "Hello", "World")
145+
fmt.Printf("< %s\n", m)
146+
147+
err = tpConn.PrintfLine("%s", m)
148+
if err != nil {
149+
return err
150+
}
151+
152+
code, message, err = tpConn.ReadCodeLine(OK)
153+
if err != nil {
154+
return err
155+
}
156+
157+
fmt.Printf("%d %s\n", code, message)
158+
159+
// GET
160+
m = fmt.Sprintf("%s %s", CmdGet, "Hello")
161+
fmt.Printf("< %s\n", m)
162+
163+
err = tpConn.PrintfLine("%s", m)
164+
if err != nil {
165+
return err
166+
}
167+
168+
code, message, err = tpConn.ReadCodeLine(OK)
169+
if err != nil {
170+
return err
171+
}
172+
173+
fmt.Printf("%d %s\n", code, message)
174+
175+
// QUIT
176+
m = CmdQuit
177+
fmt.Printf("< %s\n", m)
178+
179+
err = tpConn.PrintfLine("%s", m)
180+
if err != nil {
181+
return err
182+
}
183+
184+
code, message, err = tpConn.ReadCodeLine(OK)
185+
if err != nil {
186+
return err
187+
}
188+
189+
fmt.Printf("%d %s\n", code, message)
190+
191+
return nil
192+
}

0 commit comments

Comments
 (0)