zoukankan      html  css  js  c++  java
  • Go实现tcp代理

    nginx默认只能代理http,而且只能监听80端口,这个就不能忍了,自己撸一个

    package main
    
    import (
        "flag"
        "fmt"
        "io"
        "net"
        "os"
        "strings"
        "sync"
    )
    
    var lock sync.Mutex
    var trueList []string
    var ip string
    var list string
    
    func main() {
        flag.StringVar(&ip, "l", ":9897", "-l=0.0.0.0:9897 指定服务监听的端口")
        flag.StringVar(&list, "d", "127.0.0.1:1789,127.0.0.1:1788", "-d=127.0.0.1:1789,127.0.0.1:1788 指定后端的IP和端口,多个用','隔开")
        flag.Parse()
        trueList = strings.Split(list, ",")
        if len(trueList) <= 0 {
            fmt.Println("-l=0.0.0.0:9897 -d=127.0.0.1:1789")
            os.Exit(1)
        }
        server()
    }
    
    func server() {
        lis, err := net.Listen("tcp", ip)
        if err != nil {
            fmt.Println(err)
            return
        }
        defer lis.Close()
        for {
            conn, err := lis.Accept()
            if err != nil {
                fmt.Println("建立连接错误:%v
    ", err)
                continue
            }
            fmt.Println(conn.RemoteAddr(), conn.LocalAddr())
            go handle(conn)
        }
    }
    
    func handle(sconn net.Conn) {
        defer sconn.Close()
        ip, ok := getIP()
        if !ok {
            return
        }
        dconn, err := net.Dial("tcp", ip)
        if err != nil {
            fmt.Printf("连接%v失败:%v
    ", ip, err)
            return
        }
        ExitChan := make(chan bool, 1)
        go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
            _, err := io.Copy(dconn, sconn)
            if err != nil {
                fmt.Printf("往%v发送数据失败:%v
    ", ip, err)
            }
            ExitChan <- true
        }(sconn, dconn, ExitChan)
        go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
            _, err := io.Copy(sconn, dconn)
            if err != nil {
                fmt.Printf("从%v接收数据失败:%v
    ", ip, err)
            }
            ExitChan <- true
        }(sconn, dconn, ExitChan)
        <-ExitChan
        dconn.Close()
    }
    
    func getIP() (string, bool) {
        lock.Lock()
        defer lock.Unlock()
    
        if len(trueList) < 1 {
            return "", false
        }
        ip := trueList[0]
        trueList = append(trueList[1:], ip)
        return ip, true
    }
  • 相关阅读:
    集合赋值及for循环删除符合条件的元素
    shiro系列12:rememberme(记住我)
    shiro系列11:缓存
    shiro系列10:会话管理
    shiro系列8:授权源码解析
    shiro系列7:拦截器
    shiro系列6:授权
    shiro系列5:Realm
    shiro系列4:认证源码解析
    shiro系列3:MD5盐值加密认证流程
  • 原文地址:https://www.cnblogs.com/mignet/p/go_transfer.html
Copyright © 2011-2022 走看看