chR*_*NaN 5 javascript java java-ee websocket webrtc
为了使用对等连接点对点进行通信WebRTC API,需要实现信令.信令需要双向通信信道才能工作.WebSockets是双向沟通渠道.我想WebSockets用来实现信令,但是,我不知道如何处理这个问题.我在网上找到的所有内容都只讨论了你可以使用的不同双向通道,而不是提供如何使用它们的示例.
我JavaScript用于客户端和Java服务器端.那么,我将如何实现信令使用WebSockets?
这是我想出的一种方法。我还没有测试代码,所以,我不确定它是否有效。另外,我怀疑这是否有效。如果您有更好的解决方案,请在我的代码中查看问题,或者有任何建议可以随时详细说明。这背后的想法是让 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
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以创建 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;
Run Code Online (Sandbox Code Playgroud)
因为我们不在 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();
}
Run Code Online (Sandbox Code Playgroud)
接下来,在 WebSocket Server Endpoint 的 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();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我们剩下的就是客户端(javascript)。创建 WebSocket 变量:
var signalingSocket = new WebSocket("/SignalingServerEndpoint"); //TODO need the full and correct path to the WebSocket
Run Code Online (Sandbox Code Playgroud)
现在,对于将发送消息以“连接”到 WebSocket 服务器端点的方法:
function connect(){
var msg = {
"userId": userId
};
signalingSocket.send(JSON.stringify(msg));
Run Code Online (Sandbox Code Playgroud)
最后,我们只有客户端的 onMessage 方法(它将解密消息并可能将信息发送到另一个客户端)和所有实际的信令代码(ICE 服务器、约束等)。我不会介绍所有的信令工作,但这里有一个很好的教程。我希望这可以帮助其他面临类似问题的人。正如我所说,我还没有测试过代码,所以我不确定它是否会起作用。此外,我非常怀疑这是否会有效。但这至少是一个开始。
| 归档时间: |
|
| 查看次数: |
2649 次 |
| 最近记录: |