zoukankan      html  css  js  c++  java
  • forwardPort.go

    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;">

  • 相关阅读:
    关于GDI+的图片质量
    断点续传的Demo
    offic2007 ,offic2010安装失败 1935错误处理方案
    Easy Slider幻灯片 API
    Lazyload.js延迟加载效果
    MVC3中 多种跳转方式总结
    MVC中 DropDownList编辑默认选中的使用
    ASP.NET Session的七点认识
    easyui 的datagrid的自适应宽度的问题
    Linux常用文件操作高频使用命令
  • 原文地址:https://www.cnblogs.com/zhangboyu/p/7461900.html
Copyright © 2011-2022 走看看