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()
//开一个并发线程,接收退出信号
//下面代码 书写混乱 逻辑不清晰 但是实现了
gofunc(){
c:=make(chanos.Signal,)
signal.Notify(c,os.Interrupt,syscall.SIGTERM)
n:=
f:=func(){
<-c
n++
ifn>{
log.Println("forceshutdown")
os.Exit(-)
}
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"]=
obj["msg"]=""
paramAuth,hasAuth:=req.Form["auth"]
if!hasAuth{
log.Println("requestnoauth")
obj["code"]=
obj["msg"]="requestnoauth"
responseResult(obj,rw)
return
}
ifparamAuth[]!=*auth{
log.Println("requestauthfailed")
obj["code"]=
obj["msg"]="requestauthfailed"
responseResult(obj,rw)
return
}
paramStatus,hasStatus:=req.Form["status"]
if!hasStatus{
return
}
log.Println("param_status:",paramStatus)
ifparamStatus[]=="1"{
//启动服务
paramFromAddr,hasFromAddr:=req.Form["fromAddr"]
paramToAddr,hasToAddr:=req.Form["toAddr"]
ifgLocalConn!=nil{
gLocalConn.Close()
}
ifhasFromAddr&&hasToAddr{
goforwardPort(paramFromAddr[],paramToAddr[])
}
}
ifparamStatus[]=="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,*time.Second)
gofunc(){
_,err=io.Copy(targetConn,sourceConn)
iferr!=nil{
//log.Fatalf("io.Copyfailed:%v",err)
fmt.Println("io.Copyfailed:",err.Error())
}
}()
gofunc(){
_,err=io.Copy(sourceConn,targetConn)
iferr!=nil{
//log.Fatalf("io.Copyfailed:%v",err)
fmt.Println("io.Copyfailed:",err.Error())
}
}()
}
//
log.Println("forwardPortend.")
}
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
forwardPort.go的更多相关文章
- appium的几点总结
原文链接:http://blog.csdn.net/bear_w/article/details/50345283 1. 建立session时常用命令: DesiredCapabilities cap ...
- github之git基本命令介绍的简单整理
git 格式: git [--version] [--exec-path[=<path>]] [--html-path] [--info-path] [-p|--paginate|--no ...
- Linux防火墙配置(iptables, firewalld)
netfilter和底层实现 iptables firealld Linux中的防火墙 RHEL中有几种防火墙共存: iptables firewalld ip6tables ebtables 这些软 ...
- 我的第一个GitHub仓库
GitHub 仓库地址 https://github.com/FBean/test.git GitHub 常用命令 add--Add file contents to the index bisect ...
- 创建 Web 前端开发环境
Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower, Git 和 Grunt. ...
- Consul 启动命令
服务端: nohup consul agent -server -bootstrap-expect 1 -config-dir /etc/consul.d/ -data-dir /var/opt/co ...
- Git的常用命令的使用方法和解释
我们常用的git命令: add Add file contents to the index(将文件添加到暂存区) 用法: 保存某个文件到暂缓区:git add 文件名 保存当前路径的 ...
- Httptunnel教程
hts --forward-port localhost:22 80 htc -F 6789 192.168.10.1:80
- Git - Tutorial官方【转】
转自:http://www.vogella.com/tutorials/Git/article.html#git_rename_branch Lars Vogel Version 5.8 Copyri ...
随机推荐
- 剑指offer面试题48: 最长不含重复字符的子字符串
Given a string, find the length of the longest substring without repeating characters.(请从子字符串中找出一个最长 ...
- MongoDB学习笔记(三)
第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...
- C++笔记018:构造函数的调用规则
原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 一.默认构造函数 两个特殊的构造函数 1.默认无参构造函数 当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空 ...
- Hibernate的二级缓存策略
Hibernate的二级缓存策略的一般过程如下: 1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次 ...
- Ribbon整合Eureka组件,以实现负载均衡
1整体框架的说明 在本案例的框架里,我们将配置一个Eureka服务器,搭建三个提供相同服务的Eureka服务提供者,同时在Eureka服务调用者里引入Ribbon组件,这样,当有多个url向服务调用者 ...
- Git分支创建与合并
分支管理是Git支持多人协作和版本控制的关键,参照廖雪峰对Git的介绍,对真实开发环境中Git的使用结合实践进行梳理. 摘自:廖雪峰的官方网站 在实际开发中,我们应该按照几个基本原则进行分支管理: 首 ...
- 基于RecyclerView的瀑布流实现
fragment的布局: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xm ...
- 关于JavaScript的那些话
1.初学者动手环境----推荐Chrome的控制台(F12调用)2.JS中两个非常重要的数据类型是对象和数组.3.JavaScript 程序是用Unicode字符集编写的.4.JavaScript是区 ...
- Python3实现ICMP远控后门(上)
这几天一直在研究远控木马的一些通信协议,比如TCP,UDP,ICMP,DNS,HTTP等等,对于TCP,UDP这两种就不讲解了,因为太常见了. 大家可能对采用ICMP,DNS的木马不是很熟悉,其实这两 ...
- 手把手教你如何安装Pycharm——靠谱的Pycharm安装详细教程
今天小编给大家分享如何在本机上下载和安装Pycharm,具体的教程如下: 1.首先去Pycharm官网,或者直接输入网址:http://www.jetbrains.com/pycharm/downlo ...