Go实现简单的Socket服务端笔记(九)

采用标准库scanner实现数据分离处理粘包

参考http://feixiao.github.io/2016/05/08/bufio/
使用标准库scanner实现数据分离处理粘包

本文代码查看github:
https://github.com/zboyco/go-server/tree/step-9


直接使用scanner处理粘包,不用管理buffer,相对更加简单

修改socket.go中的handleClient函数

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
// 读取数据
func handleClient(server *Server, session *AppSession) {
// 获取连接地址
remoteAddr := session.conn.RemoteAddr()

fmt.Println("客户端[", session.ID, "]地址:", remoteAddr)

// 创建scanner
scanner := bufio.NewScanner(session.conn)

//根据协议定义分离规则
split := func(data []byte, atEOF bool) (int, []byte, error) {
if atEOF {
return 0, nil, errors.New("EOF")
}
if data[0] != '$' || data[3] != '#' {
return 0, nil, errors.New("数据异常")
}
if len(data) > 4 {
length := int16(0)
binary.Read(bytes.NewReader(data[1:3]), binary.BigEndian, &length)
if int(length)+4 <= len(data) {
return int(length) + 4, data[4 : int(length)+4], nil
}
}
return 0, nil, nil
}

// 设置分离函数
scanner.Split(split)

// 获取数据
for scanner.Scan() {
server.OnMessage(session, scanner.Bytes())
}

// 错误处理
if err := scanner.Err(); err != nil {
fmt.Println("客户端[", session.ID, "]数据接收错误, ", err)
session.conn.Close()
fmt.Println("客户端[", session.ID, "]连接已关闭!")
}
}