加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang hijack

发布时间:2020-12-16 18:37:47 所属栏目:大数据 来源:网络整理
导读:一直不太明白golang的hijack是干什么的?只知道hijack这个词是篡取的意思,难道跟网关的作用一样,把client的请求发到这个服务上,然后这个服务帮忙转发到远端server,但是看了源码后就明白这个golang hijack是干嘛的? 先看一下hijack相关的结构说明: type

一直不太明白golang的hijack是干什么的?只知道hijack这个词是篡取的意思,难道跟网关的作用一样,把client的请求发到这个服务上,然后这个服务帮忙转发到远端server,但是看了源码后就明白这个golang hijack是干嘛的?


先看一下hijack相关的结构说明:

typeHijackerinterface{
	Hijack()(net.Conn,*bufio.ReadWriter,error)
}
//返回连接接口net.Conn和ReadWriter,bufio读写的

// Hijack lets the caller take over the connection. -----翻译Hijack让调用者管理连接

// After a call to Hijack(),the HTTP server library

// will not do anything else with the connection.

// It becomes the caller's responsibility to manage

// and close the connection.

------------翻译调用Hijack后,HTTP的server不会对连接做多余的处理让用户自己管理和关闭连接

再看一下docker中对hijack的使用

dial,err:=cli.dial()//设置TCPkeepAlive做长连接
	//WhenwesetupaTCPconnectionforhijack,therecouldbelongperiods
	//ofinactivity(alongrunningcommandwithnooutput)thatincertain
	//networksetupsmaycauseECONNTIMEOUT,leavingtheclientinanunknown
	//state.SettingTCPKeepAliveonthesocketconnectionwillprohibit
	//ECONNTIMEOUTunlessthesocketconnectiontrulyisbroken
	iftcpConn,ok:=dial.(*net.TCPConn);ok{
		tcpConn.SetKeepAlive(true)
		tcpConn.SetKeepAlivePeriod(30*time.Second)
	}
	iferr!=nil{
		ifstrings.Contains(err.Error(),"connectionrefused"){
returnfmt.Errorf("CannotconnecttotheDockerdaemon.Is'dockerdaemon'runningonthishost?")
		}
		returnerr
	}
	clientconn:=httputil.NewClientConn(dial,nil)
	deferclientconn.Close()

	//Serverhijackstheconnection,error'connectionclosed'expected
	clientconn.Do(req)

	rwc,br:=clientconn.Hijack()
	//清理掉buffer这步非常重要,返回这个两个参数就是给用户自己管理连接和数据处理
	deferrwc.Close()


再看看clientconn.Hijack的实现:

func(cc*ClientConn)Hijack()(cnet.Conn,r*bufio.Reader){
	cc.lk.Lock()
	defercc.lk.Unlock()
	c=cc.c
	r=cc.r
	cc.c=nil
	cc.r=nil
	return
}
//就是在NewClientConn时候保存的net.Conn和bufio.Reader
funcNewClientConn(cnet.Conn,r*bufio.Reader)*ClientConn{
	ifr==nil{
		r=bufio.NewReader(c)
	}
	return&ClientConn{
		c:c,r:r,pipereq:make(map[*http.Request]uint),writeReq:(*http.Request).Write,}
}

最后截取部分server端针对hijack的处理:

func(c*conn)serve(){
	origConn:=c.rwc//copyitbeforeit'ssetnilonCloSEOrHijack
	deferfunc(){
		iferr:=recover();err!=nil{
			constsize=64<<10
			buf:=make([]byte,size)
			buf=buf[:runtime.Stack(buf,false)]
			c.server.logf("http:panicserving%v:%vn%s",c.remoteAddr,err,buf)
		}
		//从这里看出来hijacked状态服务端不close
		if!c.hijacked(){
			c.close()
			c.setState(origConn,StateClosed)
		}
	}()
/*......................*/	
}


总结:hijack就是不用重新建立连接或者重新构造ClientConn设置net.Conn和bufio,然后不断复用net.Conn和bufio,自己管理

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读