2018-05-14 12:45

golang tcp 动态代理转发

摘要

:none

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

             


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

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