打算闲的时候写一个tcp_pool.刚开始做,就结束了.因为我走到了死胡同.
2015-11-05 16:58
369 查看
package gyc_server_deploy import ( "errors" "fmt" "net" "sync" "time" ) var GlobalLock *sync.RWMutex = new(sync.RWMutex) type IPPool struct { IP []string Maxconn int TimeOut int64 } type ConnectionPool struct { IPPool UseConnection map[string]int Lock *sync.RWMutex Connection map[string]chan net.Conn } var returnChan chan net.Conn = make(chan net.Conn, 1000) var exitChan chan bool = make(chan bool, 1) func (this *ConnectionPool) GetConnection(ip string) *NetConnection { if list := this.Connection[ip]; len(list) > 0 { con := NetConnection{new(sync.RWMutex), <-list, returnChan} GlobalLock.Lock() this.UseConnection[ip] = this.UseConnection[ip] + 1 GlobalLock.Unlock() return &con } if this.UseConnection[ip] < this.Maxconn { c, err := dial(ip, this.TimeOut) if err != nil { fmt.Println(err) return nil } con := NetConnection{new(sync.RWMutex), c, returnChan} GlobalLock.Lock() this.UseConnection[ip] = this.UseConnection[ip] + 1 GlobalLock.Unlock() return &con } con := NetConnection{new(sync.RWMutex), <-this.Connection[ip], returnChan} GlobalLock.Lock() this.UseConnection[ip] = this.UseConnection[ip] + 1 GlobalLock.Unlock() return &con } func (this *ConnectionPool) New(ip string) error { if this.Index(ip) { if _, ok := this.Connection[ip]; !ok { ConChan := make(chan net.Conn, this.Maxconn) err := createConList(ip, ConChan, this.TimeOut) if err != nil { return err } this.Lock.Lock() this.Connection[ip] = ConChan this.Lock.Unlock() } return errors.New(fmt.Sprintf("%s: Already exists.", ip)) } ConChan := make(chan net.Conn, this.Maxconn) err := createConList(ip, ConChan, this.TimeOut) if err != nil { return err } if !this.Index(ip) { this.Lock.Lock() this.IP = append(this.IP, ip) this.Connection[ip] = ConChan this.Lock.Unlock() return nil } return errors.New(fmt.Sprintf("%s: Already exists.", ip)) } func (this *ConnectionPool) Index(ip string) bool { this.Lock.RLock() defer this.Lock.RUnlock() for _, v := range this.IP { if v == ip { return true } } return false } func (this *ConnectionPool) Close() { exitChan <- true } func (this *IPPool) Init() *ConnectionPool { M := ConnectionPool{Lock: new(sync.RWMutex), Connection: make(map[string]chan net.Conn)} for _, addr := range this.IP { ConChan := make(chan net.Conn, this.Maxconn) err := createConList(addr, ConChan, this.TimeOut) if err != nil { continue } M.Connection[addr] = ConChan } M.IP = this.IP M.TimeOut = this.TimeOut M.Maxconn = this.Maxconn M.UseConnection = make(map[string]int) go RecoveryAndExit(&M) return &M } func createConList(ip string, ConChan chan net.Conn, t int64) error { for i := 0; i < cap(ConChan); i++ { con, err := dial(ip, t) if err != nil { fmt.Println(err) continue } ConChan <- con } if len(ConChan) <= 0 { return errors.New(fmt.Sprintf("%s: can't connection.", ip)) } return nil } func dial(ip string, t int64) (net.Conn, error) { if _, err := net.ResolveTCPAddr("tcp", ip); err != nil { return nil, err } return net.DialTimeout("tcp", ip, time.Second*time.Duration(t)) } func RecoveryAndExit(pool *ConnectionPool) { for { select { case con := <-returnChan: if con == nil { GlobalLock.Lock() pool.UseConnection[ip] = pool.UseConnection[ip] - 1 GlobalLock.Unlock() continue } ip := con.RemoteAddr().String() if list, ok := pool.Connection[ip]; ok { GlobalLock.Lock() pool.UseConnection[ip] = pool.UseConnection[ip] - 1 GlobalLock.Unlock() list <- con } else { con.Close() } case exit := <-exitChan: if exit { pool.Lock.Lock() defer pool.Lock.Unlock() for k, v := range pool.Connection { num := len(v) for i := 0; i < num; i++ { con := <-v con.Close() } close(v) delete(pool.Connection, k) } return } } } } type NetConnection struct { lock *sync.RWMutex con net.Conn returnChan chan net.Conn } func (this *NetConnection) Write(b []byte) (int, error) { this.lock.RLock() defer this.lock.RUnlock() return this.con.Write(b) } func (this *NetConnection) Read(b []byte) (int, error) { this.lock.RLock() defer this.lock.RUnlock() return this.con.Read(b) } func (this *NetConnection) LocalAddr() net.Addr { this.lock.RLock() defer this.lock.RUnlock() return this.con.LocalAddr() } func (this *NetConnection) RemoteAddr() net.Addr { this.lock.RLock() defer this.lock.RUnlock() return this.con.RemoteAddr() } func (this *NetConnection) Close() { this.lock.Lock() defer this.lock.Unlock() this.con = nil this.returnChan <- this.con }
相关文章推荐
- Go 语言 Channel 实现原理精要
- Go语言将支持Android
- SQLSERVER 中GO的作用详解
- TCP版backshell的VBS脚本代码
- TCP Wrappers防火墙介绍与封锁IP地址的方法
- c语言多进程tcp服务器示例
- Golang实现的聊天程序服务端和客户端代码分享
- Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结
- 在Go语言程序中使用gojson来解析JSON格式文件
- 举例详解Go语言中os库的常用函数用法
- Go语言中函数的参数传递与调用的基本方法
- GO语言异常处理机制panic和recover分析
- 深入解析Go语言的io.ioutil标准库使用
- GO语言的IO方法实例小结
- win2003连接限制TCP连接限制
- Go语言的os包中常用函数初步归纳
- go语言执行windows下命令行的方法
- Go语言计算两个经度和纬度之间距离的方法
- Go语言排序与接口实例分析
- Go语言导出内容到Excel的方法