基于Chrome、Java、WebSocket、WebRTC实现浏览器视频通话

介绍

最近这段时间折腾了一下WebRTC,看了网上的https://apprtc.appspot.com/的例子(可能需要翻墙访问),这个例子是部署在Google App Engine上的应用程序,依赖GAE的环境,后台的语言是python,而且还依赖Google App Engine Channel API,所以无法在本地运行,也无法扩展。费了一番功夫研读了例子的python端的源代码,决定用Java实现,Tomcat7之后开始支持WebSocket,打算用WebSocket代替Google App Engine Channel API实现前后台的通讯,在整个例子中Java+WebSocket起到的作用是负责客户端之间的通信,并不负责视频的传输,视频的传输依赖于WebRTC。

实例的特点是:

实现

对于前端JS代码及用到的对象大家可以访问查看详细的代码介绍。我在这里只介绍下我改动过的地方,首先建立一个客户端实时获取状态的连接,在GAE的例子上是通过GAE Channel API实现,我在这里用WebSocket实现,代码:

function openChannel() {console.log("Opening channel.");socket = new WebSocket("ws://192.168.1.102:8080/RTCApp/websocket?u=${user}");socket.onopen = onChannelOpened;socket.onmessage = onChannelMessage;socket.onclose = onChannelClosed;}建立一个WebSocket连接,并注册相关的事件。这里通过Java实现WebSocket连接:

package org.rtc.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.catalina.websocket.StreamInbound;import org.apache.catalina.websocket.WebSocketServlet;import org.rtc.websocket.WebRTCMessageInbound;@WebServlet(urlPatterns = { "/websocket"})public class WebRTCWebSocketServlet extends WebSocketServlet {private static final long serialVersionUID = 1L;private String user;public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.user = request.getParameter("u");super.doGet(request, response);}@Overrideprotected StreamInbound createWebSocketInbound(String subProtocol) {return new WebRTCMessageInbound(user);}}如果你想实现WebSocket必须得用Tomcat7及以上版本,并且引入:catalina.jar,tomcat-coyote.jar两个JAR包,部署到Tomcat7之后得要去webapps/应用下面去删除这两个AR包否则无法启动,WebSocket访问和普通的访问最大的不同在于继承了WebSocketServlet,关于WebSocket的详细介绍大家可以访问,在这里就不再赘述。大家可以看看WebRTCMessageInbound这个类的实现:

package org.rtc.websocket;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.CharBuffer;import org.apache.catalina.websocket.MessageInbound;import org.apache.catalina.websocket.WsOutbound;public class WebRTCMessageInbound extends MessageInbound {private final String user;public WebRTCMessageInbound(String user) {this.user = user;}public String getUser(){return this.user;}@Overrideprotected void onOpen(WsOutbound outbound) {//触发连接事件,,在连接池中添加连接WebRTCMessageInboundPool.addMessageInbound(this);}@Overrideprotected void onClose(int status) {//触发关闭事件,在连接池中移除连接WebRTCMessageInboundPool.removeMessageInbound(this);}@Overrideprotected void onBinaryMessage(ByteBuffer message) throws IOException {throw new UnsupportedOperationException("Binary message not supported.");}@Overrideprotected void onTextMessage(CharBuffer message) throws IOException {}}WebRTCMessageInbound继承了MessageInbound,并绑定了两个事件,关键的在于连接事件,将连接存放在连接池中,等客户端A发起发送信息的时候将客户端B的连接取出来发送数据,看看WebRTCMessageInboundPool这个类:

package org.rtc.websocket;import java.io.IOException;import java.nio.CharBuffer;import java.util.HashMap;import java.util.Map;public class WebRTCMessageInboundPool {private static final Map<String,WebRTCMessageInbound > connections = new HashMap<String,WebRTCMessageInbound>();public static void addMessageInbound(WebRTCMessageInbound inbound){//添加连接System.out.println("user : " + inbound.getUser() + " join..");connections.put(inbound.getUser(), inbound);}public static void removeMessageInbound(WebRTCMessageInbound inbound){//移除连接connections.remove(inbound.getUser());}public static void sendMessage(String user,String message){try {//向特定的用户发送数据System.out.println("send message to user : " + user + " message content : " + message);WebRTCMessageInbound inbound = connections.get(user);if(inbound != null){inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(message));}} catch (IOException e) {e.printStackTrace();}}}WebRTCMessageInboundPool这个类中最重要的是sendMessage方法,向特定的用户发送数据。

大家可以看看这段代码:

function openChannel() {console.log("Opening channel.");socket = new WebSocket("ws://192.168.1.102:8080/RTCApp/websocket?u=${user}");socket.onopen = onChannelOpened;socket.onmessage = onChannelMessage;socket.onclose = onChannelClosed;}${user}是怎么来的呢?其实在进入这个页面之前是有段处理的:

旅游,放松心情,用眼睛享受风景。

基于Chrome、Java、WebSocket、WebRTC实现浏览器视频通话

相关文章:

你感兴趣的文章:

标签云: