func (client *TcpClient) GetRespBlock(sessionId uint32) (*Msg, error) { client.sessionMtx.RLock() session, ok := client.sessionMap[sessionId] client.sessionMtx.RUnlock() if !ok { log.Errorf("Can't get session channel(%d)", sessionId) return nil, fmt.Errorf("Can't get session channel(%d)", sessionId) } msg := <-session.sessionChan client.safeDeleteSession(sessionId) return msg, nil }
// Get reponse of a session without block.. func (client *TcpClient) GetRespNonBlock(sessionId uint32) *Msg { var msg *Msg client.sessionMtx.RLock() session, ok := client.sessionMap[sessionId] client.sessionMtx.RUnlock() if ok { select { case msg = <-session.sessionChan: client.safeDeleteSession(sessionId) default: log.Errorf("BUG: the seesonChan(%d) in finishedSessionMap should not block.", sessionId) msg = nil } } else { log.Errorf("Can't get session channel(%d)", sessionId) msg = nil } return msg }
func NewTcpClient() *TcpClient { client := &TcpClient{ connMap: make(map[string]*Connection, 10), sessionMap: make(map[uint32]*Session, 10), } //this goroutine used to check the idle connections // when this connection stays idle for 15 minutes, we will close it. go func() { for { client.mu.Lock() for addr, conn := range client.connMap { if time.Since(conn.LastUseTime()).Minutes() > 15 { delete(client.connMap, addr) conn.Disconnect() } } client.mu.Unlock() time.Sleep(5 * time.Minute) } }() //this goroutine used to check the timeout session go func(c *TcpClient) { for { c.sessionMtx.RLock() for sessionId, session := range c.sessionMap { if len(session.sessionChan) >= 1 { continue } if time.Since(session.createdTime) > 120*time.Second { select { case session.sessionChan <- NewTimeoutMsg(sessionId): default: log.Errorf("Write timeout session to session(%d) channel should not block..", sessionId) } } } c.sessionMtx.RUnlock() time.Sleep(5 * time.Second) } }(client) return client }