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

Session增加唯一ID,拆分socket中的Read方法

增加ID为了以后判断闲置超时; 拆分Read方法方便扩展协议

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

  1. 修改AppSession结构体,增加ID和activeDateTime属性,为超时管理做准备
    1
    2
    3
    4
    5
    6
    //客户端结构体
    type AppSession struct {
    ID int64 //连接唯一标识
    conn net.Conn //socket连接
    activeDateTime time.Time //最后活跃时间
    }
  2. 将socket.go 中接收数据的方法,移植到client.go中,作为AppSession的方法使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //读取数据
    func (session *AppSession) Read() ([]byte, error) {

    //定义一个数据接收Buffer
    var buf [10240]byte

    //读取数据,io.Reader 需要传入一个byte切片
    n, err := session.conn.Read(buf[0:])

    if err != nil {
    return nil, err
    }

    //更新最后活跃时间
    session.activeDateTime = time.Now()
    return buf[0:n], nil
    }

client.go完整代码如下:

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
package server

import (
"net"
"time"
)

//客户端结构体
type AppSession struct {
ID int64 //连接唯一标识
conn net.Conn //socket连接
activeDateTime time.Time //最后活跃时间
}

//发送数据
func (session *AppSession) Send(buf []byte) {
session.conn.Write(buf)
//更新最后活跃时间
session.activeDateTime = time.Now()
}

//读取数据
func (session *AppSession) Read() ([]byte, error) {

//定义一个数据接收Buffer
var buf [10240]byte

//读取数据,io.Reader 需要传入一个byte切片
n, err := session.conn.Read(buf[0:])

if err != nil {
return nil, err
}

//更新最后活跃时间
session.activeDateTime = time.Now()
return buf[0:n], nil
}

修改socket.go中handleClient函数,执行AppSession的Read来获取数据
socket.go 完整代码如下:

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
99
100
101
package server

import (
"fmt"
"net"
"time"
)

//服务结构
type Server struct {
ip string
port int
clientCounter int64
OnError func(error)
OnMessage func(*AppSession, []byte)
}

//新建一个服务
func New(ip string, port int) *Server {
return &Server{
ip: ip,
port: port,
clientCounter: 0,
}
}

//开始监听
func (server *Server) Start() {
//定义一个本机端口
localAddress, _ := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", server.ip, server.port))

//监听端口
tcpListener, err := net.ListenTCP("tcp", localAddress)

if err != nil {
fmt.Println("监听出错, ", err)
if server.OnError != nil {
server.OnError(err)
}
return
}

//程序返回后关闭socket
defer tcpListener.Close()

for {
fmt.Println("等待客户连接...")

//开始接收连接
conn, err := tcpListener.Accept()

if err != nil {
fmt.Println("客户连接失败, ", err)
if server.OnError != nil {
server.OnError(err)
}
continue
}

//客户端ID数+1
server.clientCounter++

appSession := &AppSession{
ID: server.clientCounter,
conn: conn,
activeDateTime: time.Now(),
}

//启用goroutine处理
go handleClient(server, appSession)
}
}

//读取数据
func handleClient(server *Server, session *AppSession) {
//获取连接地址
remoteAddr := session.conn.RemoteAddr()

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

for {
fmt.Println("等待接收客户[", session.ID, "]的数据...", session.activeDateTime)

bytes, err := session.Read()

if err != nil {
fmt.Println("客户[", session.ID, "]数据接收错误, ", err)
if server.OnError != nil {
server.OnError(err)
}
return
}

if server.OnMessage == nil {
fmt.Println("错误,未找到数据处理方法!")
continue
}
server.OnMessage(session, bytes)
}
}