Skip to content

Commit 8e00918

Browse files
committed
Update tcp_basic example
1 parent 14f32d7 commit 8e00918

File tree

4 files changed

+145
-83
lines changed

4 files changed

+145
-83
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# サンプルリスト
2+
3+
- [TCP:基本パターン](./tcp_basic/)
4+
- 一番基本的なパターン

examples/singleapp/socket/tcp_basic/Taskfile.yml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
version: '3'
22

33
tasks:
4-
build:
4+
default:
55
cmds:
6-
- (cd client; go build)
7-
- (cd server; go build)
6+
- task: run
87
run:
98
cmds:
10-
- task: build
9+
- task: build-server
10+
- task: build-client
1111
- task: start-server
1212
- task: run-client
13+
- task: kill-server
14+
build-server:
15+
dir: server
16+
cmds:
17+
- go build
18+
build-client:
19+
dir: client
20+
cmds:
21+
- go build
1322
start-server:
23+
dir: server
1424
cmds:
15-
- (cd server; ./server)
25+
- ./server &
1626
run-client:
27+
dir: client
1728
cmds:
18-
- (cd client; ./client)
29+
- ./client
1930
kill-server:
2031
cmds:
2132
- pkill server

examples/singleapp/socket/tcp_basic/client/main.go

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,61 +22,47 @@ import (
2222
)
2323

2424
var (
25-
appLog = log.New(os.Stdout, "[client]", 0)
26-
errLog = log.New(os.Stderr, "[client]", 0)
25+
appLog = log.New(os.Stdout, "[client] ", 0)
26+
errLog = log.New(os.Stderr, "[client] ", 0)
2727
)
2828

29-
func main() {
30-
//
31-
// 接続
32-
//
29+
func connect(protocol, localAddr, remoteAddr string) (*net.TCPConn, error) {
3330
var (
3431
getAddr = net.ResolveTCPAddr
35-
laddr = errs.Forget(getAddr("tcp", "localhost:"))
36-
raddr = errs.Forget(getAddr("tcp", "localhost:8888"))
32+
laddr = errs.Forget(getAddr(protocol, localAddr))
33+
raddr = errs.Forget(getAddr(protocol, remoteAddr))
3734
conn *net.TCPConn
3835
err error
3936
)
4037

4138
conn, err = net.DialTCP("tcp", laddr, raddr)
4239
if err != nil {
43-
errLog.Fatal(err)
40+
return nil, err
4441
}
45-
defer conn.Close()
46-
47-
appLog.Printf("connected to: %s\n", conn.RemoteAddr())
4842

49-
//
50-
// 送信
51-
//
52-
var (
53-
message = []byte("hello world")
54-
)
43+
return conn, err
44+
}
5545

56-
_, err = conn.Write(message)
46+
func send(conn *net.TCPConn, b []byte) error {
47+
_, err := conn.Write(b)
5748
if err != nil {
58-
errLog.Printf("error at conn.Write (%v)", err)
59-
return
49+
return err
6050
}
6151

62-
err = conn.CloseWrite()
63-
if err != nil {
64-
errLog.Printf("error at conn.Write (%v)", err)
65-
return
66-
}
52+
return nil
53+
}
6754

68-
//
69-
// 受信
70-
//
55+
func recv(conn *net.TCPConn) ([]byte, error) {
7156
var (
7257
buf = new(bytes.Buffer)
7358
bytesRead int
7459
)
7560

7661
for {
7762
var (
78-
chunk = make([]byte, 1)
63+
chunk = make([]byte, 3)
7964
chunkSize int
65+
err error
8066
)
8167

8268
chunkSize, err = conn.Read(chunk)
@@ -89,22 +75,62 @@ func main() {
8975
break
9076
}
9177

92-
errLog.Printf("error at conn.Read (%v)", err)
93-
return
78+
return nil, err
9479
}
9580

9681
if chunkSize == 0 {
97-
appLog.Printf("closed by remote")
98-
return
82+
return nil, errors.New("closed by remote")
9983
}
10084

10185
bytesRead += chunkSize
10286
buf.Write(chunk)
10387
}
104-
appLog.Printf("%d bytes recv", bytesRead)
10588

89+
return buf.Bytes()[:bytesRead], nil
90+
}
91+
92+
func main() {
93+
//
94+
// 接続
95+
//
96+
conn, err := connect("tcp", "localhost:", "localhost:8888")
97+
if err != nil {
98+
errLog.Printf("error at connect (%v)", err)
99+
}
100+
defer conn.Close()
101+
102+
appLog.Printf("connected to: %s\n", conn.RemoteAddr())
103+
104+
//
105+
// 送信
106+
//
106107
var (
107-
data = buf.Bytes()[:bytesRead]
108+
message = []byte("hello world")
108109
)
110+
111+
err = send(conn, message)
112+
if err != nil {
113+
errLog.Printf("error at conn.Write (%v)", err)
114+
return
115+
}
116+
appLog.Printf("%d bytes send", len(message))
117+
118+
// 対向先にEOFを伝えるために無理やり送信側ストリームを閉じる
119+
// (本来は、通信メッセージ毎の構造規約があるはずなので、このようにすることは無い。サンプルなので。)
120+
err = conn.CloseWrite()
121+
if err != nil {
122+
errLog.Printf("error at conn.Write (%v)", err)
123+
return
124+
}
125+
appLog.Println("notify EOF (conn.CloseWrite)")
126+
127+
//
128+
// 受信
129+
//
130+
data, err := recv(conn)
131+
if err != nil {
132+
errLog.Printf("error at recv (%v)", err)
133+
}
134+
appLog.Printf("%d bytes recv", len(data))
109135
appLog.Printf("recv: %s\n", data)
110136
}

examples/singleapp/socket/tcp_basic/server/main.go

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,56 @@ import (
2424
)
2525

2626
var (
27-
appLog = log.New(os.Stdout, "[server]", 0)
28-
errLog = log.New(os.Stderr, "[server]", 0)
27+
appLog = log.New(os.Stdout, "[server] ", 0)
28+
errLog = log.New(os.Stderr, "[server] ", 0)
2929
)
3030

31+
func send(conn *net.TCPConn, b []byte) error {
32+
_, err := conn.Write(b)
33+
if err != nil {
34+
return err
35+
}
36+
37+
return nil
38+
}
39+
40+
func recv(conn *net.TCPConn) ([]byte, error) {
41+
var (
42+
buf = new(bytes.Buffer)
43+
bytesRead int
44+
)
45+
46+
for {
47+
var (
48+
chunk = make([]byte, 10)
49+
chunkSize int
50+
err error
51+
)
52+
53+
chunkSize, err = conn.Read(chunk)
54+
appLog.Printf("chunk recv: %dbyte(s)\terr:%v", chunkSize, err)
55+
56+
if err != nil {
57+
if errors.Is(err, io.EOF) {
58+
bytesRead += chunkSize
59+
buf.Write(chunk)
60+
break
61+
}
62+
63+
return nil, err
64+
}
65+
66+
if chunkSize == 0 {
67+
return nil, errors.New("closed by remote")
68+
}
69+
70+
bytesRead += chunkSize
71+
buf.Write(chunk)
72+
}
73+
74+
return buf.Bytes()[:bytesRead], nil
75+
}
76+
3177
func main() {
3278
//
3379
// 起動
@@ -90,44 +136,11 @@ func main() {
90136
//
91137
// 受信
92138
//
93-
var (
94-
buf = new(bytes.Buffer)
95-
bytesRead int
96-
)
97-
98-
for {
99-
var (
100-
chunk = make([]byte, 1)
101-
chunkSize int
102-
)
103-
104-
chunkSize, err = conn.Read(chunk)
105-
appLog.Printf("chunk recv: %dbyte(s)\terr:%v", chunkSize, err)
106-
107-
if err != nil {
108-
if errors.Is(err, io.EOF) {
109-
bytesRead += chunkSize
110-
buf.Write(chunk)
111-
break
112-
}
113-
114-
appLog.Printf("error at conn.Read (%v)", err)
115-
return
116-
}
117-
118-
if chunkSize == 0 {
119-
appLog.Printf("closed by remote")
120-
return
121-
}
122-
123-
bytesRead += chunkSize
124-
buf.Write(chunk)
139+
data, err := recv(conn)
140+
if err != nil {
141+
errLog.Printf("error at recv (%v)", err)
125142
}
126-
appLog.Printf("%d bytes recv", bytesRead)
127-
128-
var (
129-
data = buf.Bytes()[:bytesRead]
130-
)
143+
appLog.Printf("%d bytes recv", len(data))
131144
appLog.Printf("recv: %s\n", data)
132145

133146
//
@@ -137,17 +150,25 @@ func main() {
137150
message = bytes.ToUpper(data)
138151
)
139152

140-
_, err = conn.Write(message)
153+
err = send(conn, message)
141154
if err != nil {
142-
errLog.Printf("error at client writeto (%v)", err)
155+
errLog.Printf("error at send (%v)", err)
143156
return
144157
}
158+
appLog.Printf("%d bytes send", len(message))
145159

160+
// 対向先にEOFを伝えるために無理やり送信側ストリームを閉じる
161+
// (本来は、通信メッセージ毎の構造規約があるはずなので、このようにすることは無い。サンプルなので。)
162+
//
163+
// サーバ側の今回の実装では、これを行わなくても defer conn.Close() で切断するので対向先にEOFが通知されるが一応入れている
146164
err = conn.CloseWrite()
147165
if err != nil {
148166
errLog.Printf("error at conn closewrite (%v)", err)
149167
return
150168
}
169+
appLog.Println("notify EOF (conn.CloseWrite)")
170+
171+
151172
}()
152173
}
153174
}

0 commit comments

Comments
 (0)