利用数据库存储路由表,然后每次建立连接的时候,客户端发送一个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)
}