使用WebSockets实现WebRTC信令

5
为了使用WebRTC API进行点对点通信,您需要实现信令传递。信令传递需要一个双向通信渠道来工作。WebSockets是一种双向通信渠道。我想使用WebSockets来实现信令传递,但是我不知道如何着手。我在网上找到的所有信息都只讨论了可以使用的不同双向通道,而没有提供有关如何使用它们的示例。
我在客户端使用JavaScript,在服务器端使用Java。那么,我应该如何使用WebSockets来实现信令传递呢?

使用Java中的WebSocket服务器实现来在两个JavaScript客户端之间转发通信。 - Benjamin Trent
1个回答

5
这是我发现如何做的方法。我还没有测试代码,所以不确定它是否可行。此外,我对这个方法的效率有所怀疑。如果你有更好的解决方案,发现我的代码有问题,或者有任何建议,请详细说明。其背后的想法是让WebSocket服务器端点过滤消息并将它们发送给适当的用户。
首先,我正在使用预定义的用户ID向客户端发送消息。 WebSocket服务器端点只知道包含会话ID的Session对象(无法更改;没有设置方法)。为了连接会话ID和用户ID,我需要一个数据库表格(比在内存中保存要可靠得多)。
然后,从客户端发送到WebSocket服务器端点的第一条消息将包含该用户的ID。这将与会话ID映射到数据库中,并且该客户端将被视为“已连接”。当然,这是在实际连接到WebSocket之后发生的。
现在,一旦“连接”,我们就可以向另一个用户发送(信令)消息,只要我们知道他们的用户ID(我假设我们知道)。WebSocket服务器端点根据收件人用户ID检查数据库以找到其会话ID。一旦找到,消息就可以发送。
最后,在客户端上,我们可以解密消息并使用相同的过程将适当的消息发送回去。
因此,正如之前所述,我们将需要一个数据库表来保存客户端的会话和用户ID。由于我在所有后端代码中都使用Java,我们将通过创建一个实体类来使用ORM(对象关系映射)来保存属性。类似这样:
    @Entity
    public class WebSocketUser {
        @Id@GeneratedValue
        private long id;
        private long userId;
        private long sessionId;

        //constructors, getters and setters
    }

现在,我们可以创建服务器端点类:
    @ServerEndpoint("/SignalingServerEndpoint")
    public class SignalingServerEndpoint {
        //these class variables will be useful for 
        //access to the database and such
        private EntityManagerFactory emf;
        private EntityManager em;
        private EntityTransaction tx;
        private TypedQuery<WebsocketUser> query;
        private WebsocketUser wsu;

因为我们不在EJB中,所以我们必须像在应用程序管理的环境中一样控制实体管理器。将onOpen和onClose方法添加到Websocket:

    @OnOpen
    public void open(Session session, Endpoint config){
        emf = Persistence.createEntityManagerFactory(""); //TODO add persistence unit reference here
        em = emf.createEntityManager();
        tx = em.getTransaction();
    }

    @OnClose
    public void close(Session session, CloseReason reason){
        //if session is closing and information still exists in the database; remove it
        if (!wsu.equals(null)){
            tx.begin();
            em.remove(wsu);
            tx.commit();
        }
        em.close();
        emf.close();
    }

接下来,在WebSocket服务器端点的onMessage方法中,我们过滤消息。我选择以JSON格式发送消息。这样可以轻松解密信息(我使用了org.json库)。onMessage方法:

    @OnMessage
    public void message(Session session, String msg){
        try {
            JSONObject obj = new JSONObject(msg);
            if (!obj.has("toUserId")){
                //adding user to the database, so they can access their session ID with their user ID
                WebsocketUser wsu = new WebsocketUser(obj.getLong("userId"), session.getId());
                tx.begin();
                em.persist(wsu);
                tx.commit();
            }else if (obj.has("toUserId")){
                //message to be sent to the user with the specified user ID
                //get session ID from database
                query = em.createQuery("SELECT u FROM WebsocketUser u WHERE u.userId = " + obj.getLong("toUserId"), WebsocketUser.class);
                wsu = (WebsocketUser) query.getSingleResult();
                Set<Session> sessions = session.getOpenSessions();
                for (Iterator<Session> i = sessions.iterator(); i.hasNext();){
                    Session s = i.next();
                    if (s.getId().equals(wsu.getSessionId())){
                        s.getAsyncRemote().sendText(obj.getString("message"));
                        break;
                    }
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

最后,我们只剩下客户端(JavaScript)部分。创建WebSocket变量:
    var signalingSocket = new WebSocket("/SignalingServerEndpoint"); //TODO need the full and correct path to the WebSocket

现在,我们来介绍一种向WebSocket服务器端点发送消息的方法:"connect"。
    function connect(){
        var msg = {
            "userId": userId
        };
        signalingSocket.send(JSON.stringify(msg));

最后,我们只需要在客户端上的onMessage方法(用于解密消息并可能向其他客户端发送信息)以及所有实际的信令代码(ICE服务器、约束等)。我不会详细介绍所有信令工作,但这里有一个很好的教程(点击此处)。希望这能帮助面临类似问题的其他人。正如我所说,我没有测试过这段代码,所以我不确定它是否有效。此外,我非常怀疑这是否有效率。但至少这是一个开始。

很抱歉,这个问题是关于如何使用Websocket传输从WEBRTC获取的MEDIADATA(视图和音频)的。你如何解决这个问题?你不能使用JSON将复杂的视频和音频数据发送到Websocket。 - Kishor Prakash
1
您需要先交换信息以建立点对点连接。一旦连接建立,使用WebRTC API发送视频和音频数据。 - chRyNaN
请分享如何将WebRTC的 'stream' 转换为数据并通过Websockets发送。同时也提供您的回答。 - Kishor Prakash
1
不要通过Websocket连接发送流数据。请查看WebRTC API。 - chRyNaN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接