webrtc 很简单,核心流程就是上面这张图。唯一需要我们实现的就是 signal sever。当然信令交换一般都是走 websocket ,我用 netty 写了一个简单的 websocket 服务。
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
JSONObject jsonObject = JSON.parseObject(msg.text());
String event = jsonObject.getString("event");
if ("register".equals(event)) {
// 注册
String userId = jsonObject.getString("userId");
if (!userMap.containsKey(userId)) {
ctx.channel().attr(userIdKey).set(userId);
userMap.put(userId, ctx.channel());
logger.info("user {} 上线", userId);
}
} else if ("sdp".equals(event) || "trickle".equals(event)) {
// sdp 和 ICE trickle 消息根据接收者直接转发给对方
logger.info("收到消息 {} {}->{} <<== {}",
event,
jsonObject.getString("sender"),
jsonObject.getString("receiver"),
jsonObject.toString());
String receiver = jsonObject.getString("receiver");
if (receiver != null && userMap.containsKey(receiver)) {
msg.retain();
userMap.get(receiver).writeAndFlush(msg);
logger.info("转发消息 {} {}->{} ==>> {}",
event,
jsonObject.getString("sender"),
jsonObject.getString("receiver"),
jsonObject.toString());
}
}
}
首先通信双方都要通过 websocket 连接到服务器,之后 ws 就可以转发信令消息了。信令就是通信双方协商通讯细节的一个过程,你用什么协议都行 http 或 websocket 或其它协议。 信令格式你随便定义,只要你能让双方通信就行。
我写死了两个用户,一个 aaaa, 一个 bbbb, 一个手机装 aaaa 用户, 另外一个手机装 bbbb 用户。
final String LOCAL_USER_ID = "bbbb";
final String RECEIVER_USER_ID = "aaaa";
很神奇没多少代码就实现了两端 P2P 聊天。
iceServerList.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));
由于这里我使用了 google 的 stun 服务器, 局域网内测试没有问题,理论上你把 websocket 信令服务部署到公网,公网上两端也是可以通信的(未测试) 。
只是一个 demo 走通了流程,各种情况,各种异常等都没有处理。
signal server: https://github.com/lesliebeijing/WebrtcSignalingDemo
源码: https://github.com/lesliebeijing/WebRtcDemo