客户端的第一步是先读取配置,从这里来看有两种配置,分别是 proxy
和 visitor
,proxy
我理解,但是 visitor
是什么东西还不太清楚,那先看 proxy
吧,看下有哪些配置项:
好像比较简单,但是似乎和配置不一样,例如 address
和 port
这些信息都没体现出现,所以这里需要探究一下转化的逻辑:
这里没啥好看了,NewService
只是做了一个结构体的初始化,然后应该核心还是在 Run()
里面:
从这里来看的职责也是比较简单的,忽略掉不感兴趣的,剩下的可能也就是 svr.ctl.Run()
了,不知道这里面又做些什么事情,结合 Server 端的表现,我猜测应该也是做连接管理的,应该认证也是在这里面完成的:
和猜测的还是比较相似的,首先是登录,这里登录是不断尝试的,10秒的尝试周期,如果不外介入的话这里会一直尝试下去,这里有两个事情很重要:
- 一个重要的东西是在
login()
里面设置的,那就是 RunId,这个 RunId 在整个 frp 中有很重要的定位作用,Client 端和 Server 端都是同步的; - control 的 connection 是在
login()
里面设置的,应该后续和 Server 端的连接都通过这个 conn 进行
在登录下面有个 ctl.worker()
,然后再后面有: CheckAndStartProxy
,所以猜测 worker
的职责应该是消息的接收发送处理,但是连接应该不会在这里面处理:
这里和 Server 端的功能是对应的,但是在代码一致性上和 Server 端不一致,风格不一致;但是无妨,且先这么看着,这个函数下面还有一个地方值得注意的就是当连接意外中断之后,会有一个重连的尝试,重连尝试成功之后,一切数据结构都会被重置,这里就包括发送和结构队列,所以可能出现掉包的情况,这个需要注意:
在认证登录完成之后应该就是 Proxy 链路的建立,第一个问题就是 Proxies 的信息从哪里来:
这里给出了答案
- 构建一个
ProxyMessage
给 Server - 将
Proxy
状态设置为ProxyStatusWaitStart
- 然后等待
messageHandler
来处理
消息的处理逻辑应该是这样的:
这里似乎没啥内容,但是可以知道的是这里提取了响应体中的两个参数:ProxyName
和 RemoteAddr
,看下具体的处理逻辑:
这里奇怪的是重新构建了一个 Proxy 对象,我猜测应该是为重连而特地做的处理?代码都在这里明面上展示了,但是连接管理不再这里展现,应该在 Run 里面,在跟踪 Run 函数的时候发现这是一个 Interface,所以得看 NewProxy
出来的对象是啥,再具体看对应的实现:
这里的 TCP 居然不做很多事情,所以到这里似乎只是保存了一条记录,没有做其他的设置了。
这里总结一下,Client 和 Server 端的整体交互图应该是这样的: