1 | https://cloud.tencent.com/developer/article/2215771 |
p2p server
需要通过stun穿透协议定时与穿透服务通信,即在定时器线程里面发送SStunLogin,再在epoll里面udp接收SStunLoginResponse表示登录成功,同时epoll里面udp需要解析SStunTransfer穿透命令,收到穿透命令后需要回复对方一个字节的包。
一个字节的穿透包不一定能发出去,比如当p2p client发起打洞标记时请求的p2p server port和p2p server外部端口对不上,那打的标记就没用,或者p2p client不是严格意义上的nat 3网络(外部端口会隔段时间变化),或者是nat 4对称型网络,基本打洞不成功。
1 | // 定时器线程:每隔30秒发送STUN登录请求 |
p2p client
首先尝试发送一个字节与p2p节点通信(可能通信不上,但会在本地路由器留下打洞标记),再向穿透服务器stun发送穿透请求,最后接收udp的响应,如果是来自穿透服务器stun的响应,根据返回码判断是否穿透请求成功,如果是收到p2p节点的1字节打洞包,说明穿透打洞成功。穿透打洞成功后再和p2p节点进行正常的udp通信,例如kcp同步建连。
p2p client穿透请求成功,只能代表p2p server正常在线,需要收到p2p2 server一个字节打洞包后,才能真正说明是打洞成功了,收到打洞包后,可以根据对方的ip和端口修改本地记录,真正请求数据时肯定按这个ip和端口进行通信。
1 | // 向P2P节点发送一个字节的数据(打洞标记) |
stun server
收到p2p server的SStunLogin后,根据uid记录对方的nat、addr和ts等信息放到map中,并回复对方SStunLoginResponse,带上p2p server的外部ip和端口,p2p server收到响应后,就知道自己的外部ip和端口了。
收到p2p client的STUN_CMD_REQUEST穿透请求后,查询当前map是否有该p2p server uid的心跳记录,如果没有,说明对方p2p server节点并未上线,如果有,转发STUN_CMD_TRANSFER穿透请求到该p2p server节点,stun收到该p2p server节点的响应后,再向p2p client响应穿透请求转发成功。