golang tcp 动态代理转发
时间:2019-08-19 04:50:12 +0800 CST 浏览:3079

利用数据库存储路由表,然后每次建立连接的时候,客户端发送一个id,代理将根据id查找对应的路由,从而实现动态代理。

package main

import …

利用数据库存储路由表,然后每次建立连接的时候,客户端发送一个id,代理将根据id查找对应的路由,从而实现动态代理。

package main

import (
    "fmt"
    "net"
    "regexp"
    "strconv"

    _ "github.com/go-sql-driver/mysql"
    "github.com/go-xorm/xorm"
    log "github.com/golang/glog"
)

var (
    bufsize int = 10240
    engine  *xorm.Engine
)

func init() {
    //创建数据库连接
    var err error
    fmt.Println("init MySQL")
    //测试修改成自己实际使用的数据库uri
    engine, err = xorm.NewEngine("mysql", `user:passwd@tcp(127.0.0.1:3306)/platformdb?charset=utf8`)
    if err != nil {
        log.Fatalln(err.Error())
    }
    engine.SetMaxIdleConns(50) //设置最大空闲连接数
    engine.SetMaxConns(500)    //设置最大连接数
    engine.ShowDebug = true    //调试
}
func main() {
    ip := "0.0.0.0"
    port := 9198
    Service(ip, port)
}
func Service(ip string, port int) {
    // , dstaddr string, dsthost string
    listen, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP(ip), port, ""})
    if err != nil {
        fmt.Println("listen error: ", err.Error())
        return
    }
    fmt.Println("init done...")
    for {
        client, err := listen.AcceptTCP()
        if err != nil {
            fmt.Println("accept error: ", err.Error())
            continue
        }
        go func() {
            //动态代理
            for {
                buf := make([]byte, bufsize)
                n, err := client.Read(buf)
                if err != nil {
                    //调试
                    fmt.Printf("ReadRequest断开连接:%s\n", err.Error())
                    client.Close()
                    break
                }
                if len(buf) != 0 {
                    fmt.Println(string(buf[:n]))
                    id_str := string(buf[:n])
                    id, _ := strconv.Atoi(id_str)
                    // time.Sleep(5 * time.Second)
                    result, err := engine.Query("SELECT roomvirtualip,port FROM connectroute WHERE id=?", id)
                    if err != nil || len(result) == 0 {
                        fmt.Println("access MySQL error:", err, len(result))
                        continue
                    }
                    dstaddr := fmt.Sprintf("%s:%s", string(result[0]["virtualip"]), string(result[0]["port"]))
                    dsthost := "Host: " + dstaddr
                    //调试
                    fmt.Printf("建立连接:client=%s server=%s\n", client.RemoteAddr().String(), dstaddr)
                    go Channal(client, dstaddr, dsthost)
                    break
                }
            }
        }()
    }
}
func Channal(client *net.TCPConn, addr string, rhost string) {
    tcpAddr, _ := net.ResolveTCPAddr("tcp4", addr)
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    if err != nil {
        fmt.Println("connection error: ", err.Error())
        client.Close()
        return
    }
    //客户端与服务端打通
    go ReadRequest(client, conn, rhost)
    go ReadResponse(conn, client)
}

//请求
func ReadRequest(lconn *net.TCPConn, rconn *net.TCPConn, dsthost string) {
    //调试
    fmt.Printf("请求:%s->%s->%s->%s\n", lconn.RemoteAddr().String(), lconn.LocalAddr().String(), rconn.LocalAddr().String(), rconn.RemoteAddr().String())
    for {
        buf := make([]byte, bufsize)
        n, err := lconn.Read(buf)
        if err != nil {
            //调试
            fmt.Printf("ReadRequest断开连接:%s\n", err.Error())
            break
        }
        mesg := changeHost(string(buf[:n]), dsthost)
        //print request
        // fmt.Println(mesg)
        rconn.Write([]byte(mesg))
    }
    lconn.Close()
    rconn.Close()
}

//响应
func ReadResponse(lconn *net.TCPConn, rconn *net.TCPConn) {
    //调试
    fmt.Printf("响应:%s->%s->%s->%s\n", lconn.RemoteAddr().String(), lconn.LocalAddr().String(), rconn.LocalAddr().String(), rconn.RemoteAddr().String())
    for {
        buf := make([]byte, bufsize)
        n, err := lconn.Read(buf)
        if err != nil {
            //调试
            fmt.Printf("ReadResponse断开连接:%s\n", err.Error())
            break
        }
        // fmt.Println(string(buf[:n]))
        rconn.Write(buf[:n])
    }
    lconn.Close()
    rconn.Close()
}
func changeHost(request string, newhost string) string {
    reg := regexp.MustCompile(`Host[^\r\n]+`)
    return reg.ReplaceAllString(request, newhost)
}


如果这篇文章对你有所帮助,可以通过下边的“打赏”功能进行小额的打赏。

本网站部分内容来源于互联网,如有侵犯版权请来信告知,我们将立即处理。


来说两句吧