添加Session容器,增加超时自动关闭Session功能
本文代码查看github:
https://github.com/zboyco/go-server/tree/step-10
要实现超时管理,就需要有个地方保存所有的会话(session),我们采用 map 来存储所有的 session ,因为 session 的保存不需要顺序,同时也有删除和增加的功能,map 正好适合.
增加一个池结构,用map实现
type sessionSource struct {
source map[int64]*AppSession //Seesion池
mutex sync.Mutex //锁
}
再增加两个参数,分别用来设置超时时间和清理间隔
代码如下
// Server 服务结构
type Server struct {
ip string //服务器IP
port int //服务器端口
clientCounter int64 //计数器
sessionSource *sessionSource //Seesion池
idleSessionTimeOut int //客户端空闲超时时间
clearIdleSessionInterval int //清空空闲会话的时间间隔,为0则不清理
OnError func(error) //错误方法
OnMessage func(*AppSession, []byte) //接收到新消息
OnNewSessionRegister func(*AppSession) //新客户端接入
OnSessionClosed func(*AppSession, string) //客户端关闭通知
}
server增加 注册session/周期性清理闲置Seesion/关闭session 三个方法
// registerSession 注册session
func (server *Server) registerSession(sessionID int64, appSession *AppSession) (bool, error) {
if server.sessionSource.source[sessionID] != nil {
return false, errors.New("SessionID已存在")
}
// 加入池
server.sessionSource.mutex.Lock()
server.sessionSource.source[sessionID] = appSession
server.sessionSource.mutex.Unlock()
// 新客户端接入通知
if server.OnNewSessionRegister != nil {
server.OnNewSessionRegister(appSession)
}
return true, nil
}
// closeSession 关闭session
func (server *Server) closeSession(session *AppSession, reason string) {
session.Close(reason)
// 从池中移除
server.sessionSource.mutex.Lock()
delete(server.sessionSource.source, session.ID)
server.sessionSource.mutex.Unlock()
}
// clearTimeoutSession 周期性清理闲置Seesion
func (server *Server) clearTimeoutSession(timeoutSecond int, interval int) {
var currentTime time.Time
if interval == 0 {
return
}
for {
time.Sleep(time.Duration(interval) * time.Second)
currentTime = time.Now()
server.mutex.Lock()
{
for key, session := range server.sessionSource {
if session.activeDateTime.Add(time.Duration(timeoutSecond) * time.Second).Before(currentTime) {
fmt.Println("客户端[", key, "]超时关闭")
session.Close("Timeout")
}
}
}
server.mutex.Unlock()
}
}