概述
WebRTC library 自带了一些例子和工具,可以用来测试和评估 WebRTC 的常用功能
代码位于 webrtc-checkout/src/examples/peerconnection 目录下,主要有如下文件
├── client
│ ├── conductor.cc
│ ├── conductor.h
│ ├── defaults.cc
│ ├── defaults.h
│ ├── flag_defs.h
│ ├── linux
│ │ ├── main.cc
│ │ ├── main_wnd.cc
│ │ └── main_wnd.h
│ ├── main.cc
│ ├── main_wnd.cc
│ ├── main_wnd.h
│ ├── peer_connection_client.cc
│ └── peer_connection_client.h
└── server
├── data_socket.cc
├── data_socket.h
├── main.cc
├── peer_channel.cc
├── peer_channel.h
├── server_test.html
├── utils.cc
└── utils.h
基本拓扑结构如下
-
一个 pc(peerconnection) server,也就是一个简单的 web server 用来在两个 client 之间交换信令,比如 SDP, ICE candidate
-
两个 pc(peerconnection) client, 通过 直接连接进行音频和视频媒体数据的传输
PC server
先看服务器类,它相对比较简单,主要功能是信令交换.
server 代码比较简单,启动一个 HTTP server, 接受 client 的连接, 将接收的数据在 client 之间进行交换 两个 client 都连接到 server 上, 发送 HTTP 请求 ”/signin" , server 把它作为一个成员(ChannelMember)加到内存中的成员列表中(PeerChannel.members)
这里有一个蹩脚的设计, 由于 server 提供的是 Http 服务,它不会主动发起请求到 client 总是等 client 来要数据(/wait),server 发现有消息缓存在内部队列(ChannelMember.queue_)中,它才把消息以 HTTP 响应告诉 client.
如果使用的是双向的 websocket 协议,就没这么麻烦了,当然这只是一个示例,怎么简单怎么来。
- 启动命令:
C:\webrtc-checkout\src\out\Default\peerconnection_server.exe --port=8888
| class | responsibility | collaborators |
|---|---|---|
| ListeningSocket | 侦听端口并接受新的连接 | DataSocket |
| DataSocket | 代表一个 HTTP 连接 | ListeningSocket |
| ChannelMember | 代表一个连接到 server 上的一个端点 | DataSocket |
| PeerChannel | 代表一个传输通道,供其中的成员之间的通信 | ChannelMember |
PC Client
client 相对麻烦一些,既要通过 server 彼此之间交换信令(sdp, candidate), 还要获取本地的音视频媒体流,发送到对端,接收远端传来的媒体流,在本地回放。
而且 client 还要处理 GUI 上与用户的交互
- 启动命令
C:\webrtc-checkout\src\out\Default\peerconnection_client.exe --autoconnect
主要的流程
participant alice
participant server
participant bob
alice->>server: sign in
server-->>alice: alice's id
bob->>server: sign in
server-->>bob: bob's id, alice's name, id
alice->>server: wait
server-->>alice: bob's name, id
alice->>server: offer(sdp)
server-->>alice: ok
bob->>server: wait
server-->>bob: offer(sdp)
bob->>server: answer(sdp)
server-->>bob: ok
alice->>server: wait
server-->>alice: answer(sdp)
alice->>server: candidate
server-->>alice: ok
bob->>server: candidate
server-->>bob: ok
alice->>server: wait
server-->>alice: bob's candidate
bob->>server: wait
server-->>bob: alice's candidate
alice->>server: sign_out
server-->>alice:ok
bob->>server: sign out
server-->>bob: ok
通过以上的信令交互, Alice 和 Bob 交换了彼此的 SDP 和 Candidate, 这样就可以搭建 PeerConnection,以 RTP 来传输彼此的音视频数据了
participant main
participant ListeningSocket as ls
participant DataSocket as s
participant PeerChannel as clients
participant ChanndleMember as member
main->ls: Create()
main->ls: Listen(port)
main->clients: create
main->main: select
main->s: OnDataAvailable()
main->clients: lookup(socket)
alt IsPeeerConnection(s)
alt !member
main->clients: AddMember(s)
clients->member: new
clients->clients: BroadcastChangedState(...)
clients->clients: HandleDeliveryFailures(...)
else
main->clients:IsTargetedRequest(s)
alt it is target
main->member: ForwardRequestToPeer(s, target)
member->member: QueueResponse(...)
else
main->s: Send(200 | 500)
end
end