簡體   English   中英

使用WebSockets實現WebRTC信令

[英]Implementing WebRTC Signaling using WebSockets

為了使用WebRTC API連接點對點進行通信,您需要實現信令。 信令需要雙向通信信道才能工作。 WebSockets是一種雙向通信通道。 我想使用WebSockets來實現信令,但是,我不知道如何處理這個問題。 我在網上找到的所有東西都只討論了你可以使用的不同雙向通道,而不是提供如何使用它們的例子。

我在客戶端使用JavaScript ,服務器端使用Java 那么,我如何使用WebSockets實現信令?

這是我弄清楚如何做到這一點的方式。 我還沒有測試過代碼,所以,我不確定它是否有效。 此外,我對這是否有效持懷疑態度。 如果您有更好的解決方案,請查看我的代碼中的問題,或者任何建議隨時詳細說明。 這背后的想法是讓WebSocket服務器端點通過消息過濾並將它們發送給適當的用戶。

  • 首先,我使用預定的用戶ID向客戶發送消息。 WebSocket服務器端點只知道包含會話ID的Session對象(不能更改;沒有set方法)。 為了鏈接會話ID和用戶ID,我需要一個數據庫表(比將其保存在內存中更可靠)。

  • 然后,從客戶端發送到WebSocket服務器端點的第一條消息將包含該用戶的ID。 這將與會話ID一起映射到數據庫,客戶端將被視為“已連接”。 當然,這在實際連接到WebSocket之后發生。

  • 現在,一旦“連接”,我們就可以向另一個用戶發送(發送信號)消息,只要我們知道他們的用戶ID(我假設我們這樣做)。 WebSocket服務器端點根據數據庫檢查收件人用戶ID以查找其會話ID。 找到后,即可發送消息。

  • 最后,在客戶端,我們可以解密消息並發回適當的消息(使用上面相同的過程)。

因此,如前所述,我們需要一個用於客戶端會話和用戶ID的數據庫表。 由於我將Java用於所有后端代碼,因此我們將使用ORM(對象關系映射)創建一個Entity類來保存屬性。 像這樣的東西:

    @Entity
    public class WebSocketUser {
        @Id@GeneratedValue
        private long id;
        private long userId;
        private long sessionId;

        //constructors, getters and setters
    }

現在,我們可以創建Server Endpoint類:

    @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服務器端點的方法:

    function connect(){
        var msg = {
            "userId": userId
        };
        signalingSocket.send(JSON.stringify(msg));

最后,我們所擁有的只是客戶端的onMessage方法(它將解密消息並可能將信息發送給其他客戶端)和所有實際的信令代碼(ICE服務器,約束等)。 我不會涉及所有信號工作,但這里有一個很好的教程 我希望這可以幫助其他人遇到類似的問題。 正如我所說,我沒有測試過代碼,所以如果它能夠正常工作,我就不會感到滿意。 此外,我非常懷疑這是否有效。 但這至少是一個開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM