当对等方位于同一网络但位于具有对称 NAT 的路由器后面时,它们是否应该能够通过 WebRTC 进行连接?这样的话就不需要ICE服务器了,应该没有问题吧?
我有两个在同一台机器上的对等点尝试相互连接,但连接失败,但这是我第一次尝试使用 WebRTC 做某事,因此我的实现可能存在缺陷:P
在 Go 中提供 Peer:
package main
import (
"fmt"
"io"
"net/http"
"strconv"
"github.com/pion/webrtc/v4"
)
func main() {
answerC := HTTPSDPServer(8000) // feeds sdp into
// Create a new RTCPeerConnection
peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{})
if err != nil {
panic(err)
}
defer func() {
if cErr := peerConnection.Close(); cErr != nil {
fmt.Printf("cannot close peerConnection: %v\n", cErr)
}
}()
peerConnection.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
fmt.Printf("Peer Connection State has changed: %s\n", s.String())
})
c, err := peerConnection.CreateDataChannel("channel", nil)
if err != nil {
panic(err)
}
c.OnOpen(func() {
fmt.Println("Data Channel OPEN")
})
c.OnClose(func() {
fmt.Println("Data Channel CLOSE")
})
offer, err := peerConnection.CreateOffer(nil)
if err != nil {
panic(err)
}
err = peerConnection.SetLocalDescription(offer)
if err != nil {
panic(err)
}
fmt.Println(strconv.Quote(offer.SDP)) // Copy this to frontend app
answerStr := <-answerC
answer := webrtc.SessionDescription{
Type: webrtc.SDPTypeAnswer,
SDP: answerStr,
}
err = peerConnection.SetRemoteDescription(answer)
if err != nil {
panic(err)
}
select {}
}
func HTTPSDPServer(port int) chan string {
sdpChan := make(chan string)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
fmt.Fprintf(w, "done")
sdpChan <- string(body)
})
go func() {
// nolint: gosec
err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
if err != nil {
panic(err)
}
}()
return sdpChan
}
Vue 前端在启动时运行此脚本:
const remoteConnection = new RTCPeerConnection()
remoteConnection.onicecandidate = e => {
console.log(" NEW ice candidnat!! on localconnection reprinting SDP ")
console.log(JSON.stringify(remoteConnection.localDescription))
}
remoteConnection.ondatachannel = e => {
const receiveChannel = e.channel;
receiveChannel.onmessage = e => console.log("message: " + e.data)
receiveChannel.onopen = e => console.log("Data Channel OPEN");
receiveChannel.onclose = e => console.log("Data Channel CLOSED");
remoteConnection.channel = receiveChannel;
}
var sdp = "PASTE OFFER HERE" // Paste SDP copied from the offering peer
var offer = { "type": "offer", "sdp": sdp }
remoteConnection.setRemoteDescription(offer).then(a => console.log("done"))
//create answer
await remoteConnection.createAnswer().then(a => remoteConnection.setLocalDescription(a)).then(a =>
console.log(JSON.stringify(remoteConnection.localDescription)))
前端应用程序打印它的 sdp 后,它会在请求中发送到提供对等方的服务器以解除阻止并继续。没有错误,连接只是从“正在连接”变为“失败”。
事实证明我错误地处理了报价创建。 我创建了一个报价,将其设置为本地描述,然后直接使用它
offer, err := peerConnection.CreateOffer(nil)
if err != nil {
panic(err)
}
err = peerConnection.SetLocalDescription(offer)
if err != nil {
panic(err)
}
// then I referenced offer.SPD to get the SPD.
我需要做的是调用
webrtc.GatheringCompletePromise(peerConnection)
并等待它完成,然后使用 peerConnection.LocalDescription().SPD
而不是 offer.SPD
这是一个完整的例子
offer, err := peerConnection.CreateOffer(nil)
if err != nil {
panic(err)
}
// Create channel that is blocked until ICE Gathering is complete
gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
err = peerConnection.SetLocalDescription(offer)
if err != nil {
panic(err)
}
<-gatherComplete
// get SPD from peerConnection.LocalDescription().SPD