github.com/zhongdalu/gf@v1.0.0/g/net/gtcp/gtcp_pool.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package gtcp 8 9 import ( 10 "time" 11 12 "github.com/zhongdalu/gf/g/container/gmap" 13 "github.com/zhongdalu/gf/g/container/gpool" 14 "github.com/zhongdalu/gf/g/errors/gerror" 15 ) 16 17 // 链接池链接对象 18 type PoolConn struct { 19 *Conn // 继承底层链接接口对象 20 pool *gpool.Pool // 对应的链接池对象 21 status int // 当前对象的状态,主要用于失败重连判断 22 } 23 24 const ( 25 gDEFAULT_POOL_EXPIRE = 60000 // (毫秒)默认链接对象过期时间 26 gCONN_STATUS_UNKNOWN = 0 // 未知,表示未经过连通性操作; 27 gCONN_STATUS_ACTIVE = 1 // 正常,表示已经经过连通性操作 28 gCONN_STATUS_ERROR = 2 // 错误,表示该接口操作产生了错误,不应当被循环使用了 29 30 ) 31 32 var ( 33 // 连接池对象map,键名为地址端口,键值为对应的连接池对象 34 pools = gmap.NewStrAnyMap() 35 ) 36 37 // 创建TCP链接池对象 38 func NewPoolConn(addr string, timeout ...int) (*PoolConn, error) { 39 var pool *gpool.Pool 40 if v := pools.Get(addr); v == nil { 41 pools.LockFunc(func(m map[string]interface{}) { 42 if v, ok := m[addr]; ok { 43 pool = v.(*gpool.Pool) 44 } else { 45 pool = gpool.New(gDEFAULT_POOL_EXPIRE, func() (interface{}, error) { 46 if conn, err := NewConn(addr, timeout...); err == nil { 47 return &PoolConn{conn, pool, gCONN_STATUS_ACTIVE}, nil 48 } else { 49 return nil, err 50 } 51 }) 52 m[addr] = pool 53 } 54 }) 55 } else { 56 pool = v.(*gpool.Pool) 57 } 58 59 if v, err := pool.Get(); err == nil { 60 return v.(*PoolConn), nil 61 } else { 62 return nil, err 63 } 64 } 65 66 // (方法覆盖)覆盖底层接口对象的Close方法 67 func (c *PoolConn) Close() error { 68 if c.pool != nil && c.status == gCONN_STATUS_ACTIVE { 69 c.status = gCONN_STATUS_UNKNOWN 70 c.pool.Put(c) 71 } else { 72 return c.Conn.Close() 73 } 74 return nil 75 } 76 77 // (方法覆盖)发送数据 78 func (c *PoolConn) Send(data []byte, retry ...Retry) error { 79 var err error 80 if err = c.Conn.Send(data, retry...); err != nil && c.status == gCONN_STATUS_UNKNOWN { 81 if v, e := c.pool.NewFunc(); e == nil { 82 c.Conn = v.(*PoolConn).Conn 83 err = c.Conn.Send(data, retry...) 84 } else { 85 err = e 86 } 87 } 88 if err != nil { 89 c.status = gCONN_STATUS_ERROR 90 } else { 91 c.status = gCONN_STATUS_ACTIVE 92 } 93 return err 94 } 95 96 // (方法覆盖)接收数据 97 func (c *PoolConn) Recv(length int, retry ...Retry) ([]byte, error) { 98 data, err := c.Conn.Recv(length, retry...) 99 if err != nil { 100 c.status = gCONN_STATUS_ERROR 101 } else { 102 c.status = gCONN_STATUS_ACTIVE 103 } 104 return data, err 105 } 106 107 // (方法覆盖)按行读取数据,阻塞读取,直到完成一行读取位置(末尾以'\n'结尾,返回数据不包含换行符) 108 func (c *PoolConn) RecvLine(retry ...Retry) ([]byte, error) { 109 data, err := c.Conn.RecvLine(retry...) 110 if err != nil { 111 c.status = gCONN_STATUS_ERROR 112 } else { 113 c.status = gCONN_STATUS_ACTIVE 114 } 115 return data, err 116 } 117 118 // (方法覆盖)带超时时间的数据获取 119 func (c *PoolConn) RecvWithTimeout(length int, timeout time.Duration, retry ...Retry) (data []byte, err error) { 120 if err := c.SetRecvDeadline(time.Now().Add(timeout)); err != nil { 121 return nil, err 122 } 123 defer func() { 124 err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") 125 }() 126 data, err = c.Recv(length, retry...) 127 return 128 } 129 130 // (方法覆盖)带超时时间的数据发送 131 func (c *PoolConn) SendWithTimeout(data []byte, timeout time.Duration, retry ...Retry) (err error) { 132 if err := c.SetSendDeadline(time.Now().Add(timeout)); err != nil { 133 return err 134 } 135 defer func() { 136 err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") 137 }() 138 err = c.Send(data, retry...) 139 return 140 } 141 142 // (方法覆盖)发送数据并等待接收返回数据 143 func (c *PoolConn) SendRecv(data []byte, receive int, retry ...Retry) ([]byte, error) { 144 if err := c.Send(data, retry...); err == nil { 145 return c.Recv(receive, retry...) 146 } else { 147 return nil, err 148 } 149 } 150 151 // (方法覆盖)发送数据并等待接收返回数据(带返回超时等待时间) 152 func (c *PoolConn) SendRecvWithTimeout(data []byte, receive int, timeout time.Duration, retry ...Retry) ([]byte, error) { 153 if err := c.Send(data, retry...); err == nil { 154 return c.RecvWithTimeout(receive, timeout, retry...) 155 } else { 156 return nil, err 157 } 158 }