pion webrtc 示例代码解析 一
pionpion 是go语言写的webrtc的开发库套装我会对他的示例一一解析启动 go run examples.go,打开datachannel点击run javascript,得到Browser base64 Session Description后复制里面的base64到一个文件中,名字为a.txt然后进入datachannel 目录go run main.go < a.txt就会得
pion webrtc
pion 是go语言写的webrtc的开发库套装
DTLS 协议
我们对DTLS 协议要适当的解释,TLS是用于TCP的,而DTLS是用于数据报的,很多应用运行在TCP之上,但是目前这种情况正在改变。现在不断增长的应用层协议,比如SIP (session initial protocol),RTP (real time protocol), MGCP (the Media Gateway Control Protocol),还有许多游戏协议都基于UDP传输而设计,而HTTP协议也正悄然改变,HTTP3可能也会转移到udp上。那么webrtc的datachannel也是基于这个协议的。
DataChannel的数据通过boringssl加密后再通过udp发送给对端,实现了DTLS,发送datachannel数据和音视频数据的事实上是同一个sock。不过不一样的是:音视频数据传输使用了RTP协议,并且通过NACK和FEC算法来抗丢包,而DataChannel底层使用了SCTP(stream control transmission protocol)协议,SCTP和TCP类似,具备流量控制、拥塞控制,可以说是一个可靠性传输协议,因此可以不采取其它措施即,就已经实现DataChannel数据的可靠传输。webrtc采用了第三方开源库usrsctplib来实现SCTP协议。
pion示例代码
这里,我们会对pion的示例一一解析,首先:启动 go run examples.go, ,example.go 是一个http协议的服务器,默认在80端口启动协议,这里我们打开网页后,打开datachannel示例:
点击run javascript后,得到Browser base64 Session Description框里的数据,复制里面的base64到一个文件中,保存名字为a.txt ![data channel 示例](https://img-blog.csdnimg.cn/6cd3bbdfc5dd44fba6fa57a9c288306c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5ibzA0MjMxMQ==,size_16,color_FFFFFF,t_70) 然后进入datachannel 目录 go run main.go < a.txt 就会得到自己的sdp信息,将这个sdp信息复制到页面中, ![复制进去](https://img-blog.csdnimg.cn/3a8f9b70a01b4558bf5b3a8ad6049023.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5ibzA0MjMxMQ==,size_16,color_FFFFFF,t_70) 点击Start session, 网页和客户端可以开始互相发送信息。
示例datachannel
offer := webrtc.SessionDescription{}
signal.Decode(signal.MustReadStdin(), &offer)
singal 需要对输入进行读取,所以要从参数上输入offer,offer是一串码,sdp信息,我们来看看解码后的字符串:
{
offer v=0
o=- 203838700267639233 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS
m=application 3002 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 1.86.247.81
a=candidate:2026329132 1 udp 2122260223 192.168.0.129 51720 typ host generation 0 network-id 1
a=candidate:910469340 1 tcp 1518280447 192.168.0.129 9 typ host tcptype active generation 0 network-id 1
a=candidate:4186919576 1 udp 1686052607 1.86.247.81 3002 typ srflx raddr 192.168.0.129 rport 51720 generation 0 network-id 1
a=ice-ufrag:y7zo
a=ice-pwd:vYIYqME4lmB5i0C3JwVZQicy
a=ice-options:trickle
a=fingerprint:sha-256 A2:28:50:C3:45:9D:19:12:6D:29:C5:32:06:97:C7:D2:37:9F:EA:A2:02:68:58:91:76:E6:44:17:8D:B9:C6:A8
a=setup:actpass
a=mid:0
a=sctp-port:5000
a=max-message-size:262144
}
这下看的很清晰了
package main
import (
"fmt"
"os"
"time"
"github.com/pion/webrtc/v3"
"github.com/pion/webrtc/v3/examples/internal/signal"
)
func main() {
// Everything below is the Pion WebRTC API! Thanks for using it ❤️.
// Prepare the configuration
config := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}
// Create a new RTCPeerConnection
peerConnection, err := webrtc.NewPeerConnection(config)
if err != nil {
panic(err)
}
defer func() {
if cErr := peerConnection.Close(); cErr != nil {
fmt.Printf("cannot close peerConnection: %v\n", cErr)
}
}()
// Set the handler for Peer connection state
// This will notify you when the peer has connected/disconnected
peerConnection.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
fmt.Printf("Peer Connection State has changed: %s\n", s.String())
if s == webrtc.PeerConnectionStateFailed {
// Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart.
// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
fmt.Println("Peer Connection has gone to failed exiting")
os.Exit(0)
}
})
// Register data channel creation handling
peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
fmt.Printf("New DataChannel %s %d\n", d.Label(), d.ID())
// Register channel opening handling
d.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID())
for range time.NewTicker(5 * time.Second).C {
message := signal.RandSeq(15)
fmt.Printf("Sending '%s'\n", message)
// Send the message as text
sendErr := d.SendText(message)
if sendErr != nil {
panic(sendErr)
}
}
})
// Register text message handling
d.OnMessage(func(msg webrtc.DataChannelMessage) {
fmt.Printf("Message from DataChannel '%s': '%s'\n", d.Label(), string(msg.Data))
})
})
// Wait for the offer to be pasted
offer := webrtc.SessionDescription{}
signal.Decode(signal.MustReadStdin(), &offer)
// Set the remote SessionDescription
err = peerConnection.SetRemoteDescription(offer)
if err != nil {
panic(err)
}
// Create an answer
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
}
// Create channel that is blocked until ICE Gathering is complete
gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
// Sets the LocalDescription, and starts our UDP listeners
err = peerConnection.SetLocalDescription(answer)
if err != nil {
panic(err)
}
// Block until ICE Gathering is complete, disabling trickle ICE
// we do this because we only can exchange one signaling message
// in a production application you should exchange ICE Candidates via OnICECandidate
<-gatherComplete
// Output the answer in base64 so we can paste it in browser
fmt.Println(signal.Encode(*peerConnection.LocalDescription()))
// Block forever
select {}
}
网页和客户端
网页和客户端的api 非常接近,可以看出pion是非常友好的,可以根据这个 示例来制作点对点的聊天程序。
更多推荐
所有评论(0)