# 5.5 调试客户端
# 5.5.1 基础介绍
调试客户端作为日常开发调试的一种重要工具,为游戏开发者提供了非常便捷的接口方案。开发者可以借助flag (opens new window)包来接收不同的输入参数从而控制不同的客户端行为。同时,框架提供的调试客户端也具备非常出色的性能,也可以作为压测客户端来使用。
# 5.5.2 TCP客户端示例
以下完整示例详见:client-tcp-example (opens new window)
- 创建项目
$ mkdir client-tcp-example
1
- 安装依赖
$ cd client-tcp-example
$ go mod init client-tcp-example
$ go get github.com/dobyte/due/v2@v2.4.2
$ go get github.com/dobyte/due/network/tcp/v2@e5cd009
1
2
3
4
2
3
4
- 启动配置
文件位置:client-tcp-example/etc/etc.toml (opens new window)
# 进程号
pid = "./run/due.pid"
# 开发模式。支持模式:debug、test、release(设置优先级:配置文件 < 环境变量 < 运行参数 < mode.SetMode())
mode = "debug"
# 统一时区设置。项目中的时间获取请使用xtime.Now()
timezone = "Local"
# 容器关闭最大等待时间。支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为0
shutdownMaxWaitTime = "0s"
[cluster.client]
# 实例ID,集群中唯一。不填写默认自动生成唯一的实例ID
id = ""
# 实例名称
name = "client"
# 编解码器。可选:json | proto。默认为proto
codec = "json"
[network.tcp.client]
# 拨号地址
addr = "127.0.0.1:3553"
# 拨号超时时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为5s
timeout = "5s"
# CA证书文件
caFile = ""
# 证书域名
serverName = ""
# 心跳间隔时间;设置为0则不启用心跳检测,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为10s
heartbeatInterval = "10s"
[packet]
# 字节序,默认为big。可选:little | big
byteOrder = "big"
# 路由字节数,默认为2字节
routeBytes = 2
# 序列号字节数,默认为2字节
seqBytes = 2
# 消息字节数,默认为5000字节
bufferBytes = 5000
# 是否携带服务器心跳时间
heartbeatTime = false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- 编写示例
文件位置:client-tcp-example/main.go (opens new window)
package main
import (
"fmt"
"time"
"github.com/dobyte/due/network/tcp/v2"
"github.com/dobyte/due/v2"
"github.com/dobyte/due/v2/cluster"
"github.com/dobyte/due/v2/cluster/client"
"github.com/dobyte/due/v2/log"
"github.com/dobyte/due/v2/utils/xtime"
)
// 路由号
const greet = 1
func main() {
// 创建容器
container := due.NewContainer()
// 创建客户端组件
component := client.NewClient(
client.WithClient(tcp.NewClient()),
)
// 初始化监听
initApp(component.Proxy())
// 添加客户端组件
container.Add(component)
// 启动容器
container.Serve()
}
// 初始化应用
func initApp(proxy *client.Proxy) {
// 监听组件启动
proxy.AddHookListener(cluster.Start, startHandler)
// 监听连接建立
proxy.AddEventListener(cluster.Connect, connectHandler)
// 监听消息回复
proxy.AddRouteHandler(greet, greetHandler)
}
// 组件启动处理器
func startHandler(proxy *client.Proxy) {
if _, err := proxy.Dial(); err != nil {
log.Errorf("connect server failed: %v", err)
return
}
}
// 连接建立处理器
func connectHandler(conn *client.Conn) {
doPushMessage(conn)
}
// 消息回复处理器
func greetHandler(ctx *client.Context) {
res := &greetRes{}
if err := ctx.Parse(res); err != nil {
log.Errorf("invalid response message, err: %v", err)
return
}
if res.Code != 0 {
log.Errorf("node response failed, code: %d", res.Code)
return
}
log.Info(res.Message)
time.AfterFunc(time.Second, func() {
doPushMessage(ctx.Conn())
})
}
// 请求
type greetReq struct {
Message string `json:"message"`
}
// 响应
type greetRes struct {
Code int `json:"code"`
Message string `json:"message"`
}
// 推送消息
func doPushMessage(conn *client.Conn) {
if err := conn.Push(&cluster.Message{
Route: 1,
Data: &greetReq{
Message: fmt.Sprintf("I'm client, and the current time is: %s", xtime.Now().Format(xtime.DateTime)),
},
}); err != nil {
log.Errorf("push message failed: %v", err)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
- 启动服务
$ cd client-tcp-example
$ go run main.go
____ __ ________
/ __ \/ / / / ____/
/ / / / / / / __/
/ /_/ / /_/ / /___
/_____/\____/_____/
┌──────────────────────────────────────────────────────┐
| [Website] https://github.com/dobyte/due |
| [Version] v2.4.2 |
└──────────────────────────────────────────────────────┘
┌────────────────────────Global────────────────────────┐
| PID: 8864 |
| Mode: debug |
| Time: 2025-10-25 10:46:23.4062229 +0800 CST |
└──────────────────────────────────────────────────────┘
┌────────────────────────Client────────────────────────┐
| Name: client |
| Codec: json |
| Protocol: tcp |
| Encryptor: - |
└──────────────────────────────────────────────────────┘
INFO[2025/10/25 10:46:23.410469] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:46:23
INFO[2025/10/25 10:46:24.413036] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:46:24
INFO[2025/10/25 10:46:25.423296] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:46:25
INFO[2025/10/25 10:46:26.424702] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:46:26
INFO[2025/10/25 10:46:27.426387] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:46:27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3.5.3 WS客户端示例
以下完整示例详见:client-ws-example (opens new window)
- 创建项目
$ mkdir client-ws-example
1
- 安装依赖
$ cd client-ws-example
$ go mod init client-ws-example
$ go get github.com/dobyte/due/v2@v2.4.2
$ go get github.com/dobyte/due/network/ws/v2@e5cd009
1
2
3
4
2
3
4
- 启动配置
文件位置:client-ws-example/etc/etc.toml (opens new window)
# 进程号
pid = "./run/due.pid"
# 开发模式。支持模式:debug、test、release(设置优先级:配置文件 < 环境变量 < 运行参数 < mode.SetMode())
mode = "debug"
# 统一时区设置。项目中的时间获取请使用xtime.Now()
timezone = "Local"
# 容器关闭最大等待时间。支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为0
shutdownMaxWaitTime = "0s"
[cluster.client]
# 实例ID,集群中唯一。不填写默认自动生成唯一的实例ID
id = ""
# 实例名称
name = "client"
# 编解码器。可选:json | proto。默认为proto
codec = "json"
[network.ws.client]
# 拨号地址
url = "ws://127.0.0.1:3553"
# 握手超时时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为10s
handshakeTimeout = "10s"
# 心跳间隔时间;设置为0则不启用心跳检测,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为10s
heartbeatInterval = "10s"
[packet]
# 字节序,默认为big。可选:little | big
byteOrder = "big"
# 路由字节数,默认为2字节
routeBytes = 2
# 序列号字节数,默认为2字节
seqBytes = 2
# 消息字节数,默认为5000字节
bufferBytes = 5000
# 是否携带服务器心跳时间
heartbeatTime = false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
- 编写示例
文件位置:client-ws-example/main.go (opens new window)
package main
import (
"fmt"
"time"
"github.com/dobyte/due/network/ws/v2"
"github.com/dobyte/due/v2"
"github.com/dobyte/due/v2/cluster"
"github.com/dobyte/due/v2/cluster/client"
"github.com/dobyte/due/v2/log"
"github.com/dobyte/due/v2/utils/xtime"
)
// 路由号
const greet = 1
func main() {
// 创建容器
container := due.NewContainer()
// 创建客户端组件
component := client.NewClient(
client.WithClient(ws.NewClient()),
)
// 初始化监听
initApp(component.Proxy())
// 添加客户端组件
container.Add(component)
// 启动容器
container.Serve()
}
// 初始化应用
func initApp(proxy *client.Proxy) {
// 监听组件启动
proxy.AddHookListener(cluster.Start, startHandler)
// 监听连接建立
proxy.AddEventListener(cluster.Connect, connectHandler)
// 监听消息回复
proxy.AddRouteHandler(greet, greetHandler)
}
// 组件启动处理器
func startHandler(proxy *client.Proxy) {
if _, err := proxy.Dial(); err != nil {
log.Errorf("connect server failed: %v", err)
return
}
}
// 连接建立处理器
func connectHandler(conn *client.Conn) {
doPushMessage(conn)
}
// 消息回复处理器
func greetHandler(ctx *client.Context) {
res := &greetRes{}
if err := ctx.Parse(res); err != nil {
log.Errorf("invalid response message, err: %v", err)
return
}
if res.Code != 0 {
log.Errorf("node response failed, code: %d", res.Code)
return
}
log.Info(res.Message)
time.AfterFunc(time.Second, func() {
doPushMessage(ctx.Conn())
})
}
// 请求
type greetReq struct {
Message string `json:"message"`
}
// 响应
type greetRes struct {
Code int `json:"code"`
Message string `json:"message"`
}
// 推送消息
func doPushMessage(conn *client.Conn) {
if err := conn.Push(&cluster.Message{
Route: 1,
Data: &greetReq{
Message: fmt.Sprintf("I'm client, and the current time is: %s", xtime.Now().Format(xtime.DateTime)),
},
}); err != nil {
log.Errorf("push message failed: %v", err)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
- 启动服务
$ cd client-ws-example
$ go run main.go
____ __ ________
/ __ \/ / / / ____/
/ / / / / / / __/
/ /_/ / /_/ / /___
/_____/\____/_____/
┌──────────────────────────────────────────────────────┐
| [Website] https://github.com/dobyte/due |
| [Version] v2.4.2 |
└──────────────────────────────────────────────────────┘
┌────────────────────────Global────────────────────────┐
| PID: 20840 |
| Mode: debug |
| Time: 2025-10-25 10:38:21.6446444 +0800 CST |
└──────────────────────────────────────────────────────┘
┌────────────────────────Client────────────────────────┐
| Name: client |
| Codec: json |
| Protocol: ws |
| Encryptor: - |
└──────────────────────────────────────────────────────┘
INFO[2025/10/25 10:38:21.651187] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:38:21
INFO[2025/10/25 10:38:22.654799] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:38:22
INFO[2025/10/25 10:38:23.656016] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:38:23
INFO[2025/10/25 10:38:24.657855] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:38:24
INFO[2025/10/25 10:38:25.659807] main.go:70 I'm tcp server, and the current time is: 2025-10-25 10:38:25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
← 5.4 Web服务器 6.1 GORM →