webrtc信令服务器搭建

  webrtc交互流程中需要一个信令服务器来转发sdp以及ice-candidate。

  webrtc规范里面并没有说明其实现方式,但其实从html技术栈中不难看出,要么用http,要么用websocket。

 

  我们使用websocket来实现。

  我使用的是servlet容器(tomcat)来实现。

 

  首先是需要安装eclipse-jee版本。

  然后下载tomcat(只是编译时需要他的jar包)

  

  然后创建web项目(servlet3项目已经不用web.xml了,以注解代替文件配置,在java里面已经使用了超过十年时间)

  

  其他的都不需要,我们只需要创建一个java类,并编写一个websocket处理程序即可。

package wrd;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/room")
public class RoomEndpoint {

    private static final String ID_KEY = "id";
    private static final String MID_SET_OK = "{\"success\":true,\"code\":0}";
    private static final String MID_SET_FAILD_DUP = "{\"success\":false,\"code\":-1,\"msg\":\"登录失败,ID重复。如果存在前次登录,可能需要退出后等待一分钟超时。\"}";
    private static final String SEND_FAILD_NLOGIN = "{\"success\":false,\"code\":-2,\"msg\":\"发送数据失败,未登录。\"}";
    private static final String SEND_FAILD_NOTFOUND = "{\"success\":false,\"code\":-3,\"msg\":\"发送数据失败,对方不在线。\"}";
    
    // id与会话的对应关系
    private static Map<String, Session> id2Session = new ConcurrentHashMap<>();
    
    @OnMessage
    public void onMessage(Session ses, String msg) throws IOException {
        if (msg.startsWith(":mid:")) {
             // 设置自身id
             var mid = msg.substring(5);
             String currentMid = (String) ses.getUserProperties().get(ID_KEY);
             if (mid.equals(currentMid)) {
                 ses.getBasicRemote().sendText(MID_SET_OK);
                 return;
             }
             if (id2Session.putIfAbsent(mid, ses) != null) {
                 ses.getBasicRemote().sendText(MID_SET_FAILD_DUP);
                 return;
             }
             if (currentMid != null) {
                 id2Session.remove(currentMid);
             }
             ses.getUserProperties().put(ID_KEY, mid);
             ses.getBasicRemote().sendText(MID_SET_OK);
             return;
        }
        
        if (msg.contains("::")) {
            if (!ses.getUserProperties().containsKey(ID_KEY)) {
                ses.getBasicRemote().sendText(SEND_FAILD_NLOGIN);
                return;
            }
            int idx = msg.indexOf("::");
            if (idx < 1) return;
            var peerId = msg.substring(0, idx);
            if (peerId.equals(ses.getUserProperties().get(ID_KEY))) return;
            var data = msg.substring(idx + 2);
            var peer = id2Session.get(peerId);
            if (peer == null) {
                ses.getBasicRemote().sendText(SEND_FAILD_NOTFOUND);
            } else {
                peer.getBasicRemote().sendText(data);
            }
            return;
        }
    }

    @OnOpen
    public void onOpen(Session ses) {
        // 一分钟超时
        ses.setMaxIdleTimeout(60 * 1000);
        // 收发文字的最大长度。默认的8192有点小,可能会不够存储较长的SDP
        ses.setMaxTextMessageBufferSize(65536);
    }
    
    @OnClose
    public void onClose(Session ses) {
        String mid = (String) ses.getUserProperties().get(ID_KEY);
        if (mid != null) {
            id2Session.remove(mid);
        }
    }
}
RoomEndpoint.java

  然后导出war包。

  

 

 

  部署到服务器上也十分简单,我们首先安装tomcat。

  

  (我使用ubuntu)

  然后使用scp把文件传上去(scp是ssh的一个工具,可以上传下载文件,支持文件夹)

  

  顺利的话,我们传上去的一瞬间,tomcat自己就发现了,并且帮我们部署好了。

  

  

  最后测试一下

  

 

 

  webrtc技术中,最不值一提的就是信令服务器,可能几行代码就写完了,实在是没什么可讲的。

 

  最后修改时间 2022-10-20 15:05:17

posted @ 2022-10-20 15:05  云中双月  阅读(1208)  评论(1)    收藏  举报