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

增加AppSession结构体

OnMessage返回AppSession结构体,提供Send方法,服务器可以主动向客户端发送数据

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

新建一个AppSession结构体,将客户端会话放在AppSession中,方便扩展和管理

  1. 在server目录中增加client.go文件
    代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
package server

import "net"

//客户端结构体
type AppSession struct {
conn net.Conn //socket连接
}

func (client *AppSession) Send(buf []byte) {
client.conn.Write(buf)
}

  1. 修改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
package server

import (
"fmt"
"net"
)

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

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

//开始监听
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
}

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

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

fmt.Println("客户地址:", remoteAddr)

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

for {
fmt.Println("等待接收数据...")
//读取数据,io.Reader 需要传入一个byte切片
n, err := conn.Read(buf[0:])

if err != nil {
fmt.Println("数据接收错误, ", err)
if server.OnError != nil {
server.OnError(err)
}
return
}

if server.OnMessage == nil {
fmt.Println("错误,未找到数据处理方法!")
continue
}
server.OnMessage(&AppSession{
conn: conn,
}, buf[0:n])
}
}

主要修改了handleClient最后调用onmessage方法,传入了一个AppSession的指针

  1. 修改main.go
    修改onMessage参数类型为AppSession
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
package main

import (
"fmt"
"go-server/server"
)

func main() {
fmt.Println("hello golang!!!")

mainServer := server.New("127.0.0.1", 9043)

mainServer.OnMessage = onMessage

mainServer.OnError = onError

mainServer.Start()
}

//接收数据方法
func onMessage(client *server.AppSession, bytes []byte) {
//将bytes转为字符串
result := string(bytes)

//输出结果
fmt.Println("接收到数据:", result)

client.Send([]byte("Got!"))
}

//接收错误方法
func onError(err error) {
//输出结果
fmt.Println("错误: ", err)
}