当前位置: 首页 > 工具软件 > forwardPort > 使用案例 >

forwardPort.go

须敏学
2023-12-01
packagemain
 
 
import(
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "log"
    "net"
    "net/http"
    "os"
    "os/signal"
    "runtime"
    "sync"
    "syscall"
    "time"
)
//监听服务地址  默认使用8000端口  服务端监听端口
varrestApiServer=flag.String("restApi","","listenaddrforrestapi")
//监听服务认证  密码
varauth=flag.String("auth","taven123","restApiPassword")
//本地监听器
vargLocalConnnet.Listener
//客户端与服务链接关系--映射
varclientSMapmap[string]net.Conn
//目标服务器和本地服务器  两个服务地址之间使用“-”链接
varforwardInfostring
 
 
funcmain(){
 
 
    clientSMap=make(map[string]net.Conn)
 
 
    //解析传入的参数
    flag.Parse()
//默认使用8000端口  服务端监听端口
    if*restApiServer==""{
        *restApiServer="0.0.0.0:8000"
    }
//开启监听服务
    goStartHttpServer(*restApiServer)
 
 
    log.Println("restApiServer:",*restApiServer)
    fmt.Println("------------启动成功------------")
 
 
    //开启线程同步锁
    varwsync.WaitGroup
    w.Add(2)
 
 
    //开一个并发线程,接收退出信号
       //下面代码  书写混乱  逻辑不清晰   但是实现了
    gofunc(){
        c:=make(chanos.Signal,1)
        signal.Notify(c,os.Interrupt,syscall.SIGTERM)
        n:=0
        f:=func(){
            <-c
            n++
            ifn>2{
                log.Println("forceshutdown")
                os.Exit(-1)
            }
            log.Println("receivedsignal,shutdown")
                     //释放相关资源
            closeAllConn()
        }
        f()
        gofunc(){
            for{
                f()
            }
        }()
        //执行完成一次,Done()等同于Add(-1),计数不为0,则阻塞
        w.Done()
    }()
 
 
    loop:=func(){
        w.Done()
 
 
    }
    loop()
    w.Wait()
 
 
    fmt.Println("------------程序执行完成------------")
 
 
}
 
 
funcStartHttpServer(addrstring){
 
 
    http.HandleFunc("/ServerSummary",ServerSummary)
    http.HandleFunc("/ForwardWork",ForwardWork)
 
 
    //
    err:=http.ListenAndServe(addr,http.DefaultServeMux)
 
 
    iferr!=nil{
        fmt.Println("ListenAndServeerror:",err.Error())
    }
 
 
}
 
 
funcServerSummary(rwhttp.ResponseWriter,req*http.Request){
    log.Println("ServerSummary")
    obj:=make(map[string]interface{})
    obj["runtime_NumGoroutine"]=runtime.NumGoroutine()
    obj["runtime_GOOS"]=runtime.GOOS
    obj["runtime_GOARCH"]=runtime.GOARCH
    obj["restApi_Addr"]=*restApiServer
    obj["server_Time"]=time.Now()
    obj["clients_Count"]=len(clientSMap)
 
 
    varclist[]string
    forcId,_:=rangeclientSMap{
        clist=append(clist,cId)
    }
    obj["clients_List"]=clist
    obj["forwardInfo"]=forwardInfo
 
 
    res,err:=json.Marshal(obj)
    iferr!=nil{
        log.Println("jsonmarshal:",err)
        return
    }
 
 
    rw.Header().Add("Content-Type","application/json;charset=utf-8")
    _,err=rw.Write(res)
    iferr!=nil{
        log.Println("writeerr:",err)
    }
    return
}
 
 
funcForwardWork(rwhttp.ResponseWriter,req*http.Request){
    req.ParseForm()
 
 
    obj:=make(map[string]interface{})
    obj["code"]=0
    obj["msg"]=""
 
 
    paramAuth,hasAuth:=req.Form["auth"]
    if!hasAuth{
        log.Println("requestnoauth")
        obj["code"]=1
        obj["msg"]="requestnoauth"
        responseResult(obj,rw)
        return
 
 
    }
 
 
    ifparamAuth[0]!=*auth{
        log.Println("requestauthfailed")
        obj["code"]=1
        obj["msg"]="requestauthfailed"
        responseResult(obj,rw)
 
 
        return
    }
 
 
    paramStatus,hasStatus:=req.Form["status"]
    if!hasStatus{
        return
 
 
    }
 
 
    log.Println("param_status:",paramStatus)
 
 
    ifparamStatus[0]=="1"{
        //启动服务
        paramFromAddr,hasFromAddr:=req.Form["fromAddr"]
        paramToAddr,hasToAddr:=req.Form["toAddr"]
        ifgLocalConn!=nil{
            gLocalConn.Close()
        }
 
 
        ifhasFromAddr&&hasToAddr{
            goforwardPort(paramFromAddr[0],paramToAddr[0])
        }
    }
 
 
    ifparamStatus[0]=="0"{
        //关闭服务
        closeAllConn()
        forwardInfo=""
    }
 
 
    responseResult(obj,rw)
 
 
    return
 
 
}
 
 
funcresponseResult(datamap[string]interface{},rwhttp.ResponseWriter){
    res,err:=json.Marshal(data)
    iferr!=nil{
        log.Println("jsonmarshal:",err)
        return
    }
 
 
    rw.Header().Add("Content-Type","application/json;charset=utf-8")
    _,err=rw.Write(res)
    iferr!=nil{
        log.Println("writeerr:",err)
    }
}
 
 
funccloseAllConn(){
    forcId,conn:=rangeclientSMap{
        log.Println("clientMapid:",cId)
        conn.Close()
        delete(clientSMap,cId)
    }
 
 
    ifgLocalConn!=nil{
        gLocalConn.Close()
        log.Println("ListenerClose")
    }else{
        gLocalConn=nil
        log.Println("Listenersettonil",gLocalConn)
    }
}
//通读全部代码 发现这里存在未释放资源 targetPort 。准确说 需要先释放sourcePort 资源  再释放targetPort 资源
funcforwardPort(sourcePortstring,targetPortstring){
 
 
    fmt.Println("sourcePort:",sourcePort,"targetPort:",targetPort)
 
 
    localConn,err:=net.Listen("tcp",sourcePort)
 
 
    iferr!=nil{
        fmt.Println(err.Error())
        return
    }
 
 
    gLocalConn=localConn
 
 
    fmt.Println("服务启动成功,服务地址:",sourcePort)
 
 
    forwardInfo=fmt.Sprintf("%s-%s",sourcePort,targetPort)
 
 
    for{
        fmt.Println("ReadytoAccept...")
        sourceConn,err:=gLocalConn.Accept()
 
 
        iferr!=nil{
            log.Println("servererr:",err.Error())
            break
        }
        //log.Println("client",sc.id,"createsession",sessionId)
 
 
        id:=sourceConn.RemoteAddr().String()
        clientSMap[id]=sourceConn
 
 
        fmt.Println("conn.RemoteAddr().String():",id)
 
 
        //targetPort:="172.16.128.83:22"
        targetConn,err:=net.DialTimeout("tcp",targetPort,30*time.Second)
 
 
        gofunc(){
            _,err=io.Copy(targetConn,sourceConn)
            iferr!=nil{
                //log.Fatalf("io.Copy1failed:%v",err)
                fmt.Println("io.Copy1failed:",err.Error())
            }
        }()
 
 
        gofunc(){
            _,err=io.Copy(sourceConn,targetConn)
            iferr!=nil{
                //log.Fatalf("io.Copy2failed:%v",err)
                fmt.Println("io.Copy2failed:",err.Error())
            }
        }()
 
 
    }
 
 
    //
    log.Println("forwardPortend.")
 
 
}
 
 

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 
 
 
 

转载于:https://www.cnblogs.com/zhangboyu/p/7461900.html

 类似资料:

相关阅读

相关文章

相关问答