这两天终于是抽了时间把WebRTC搞定了,去年就想弄的,但是确实没时间,而且那时候javaEE的websocket还没有规范,网上也都是用的tomcat自己的websocket实现的,或者还使用了一些ajax辅助,javaEE7中有了websocket的规范,tomcat也支持,所以最近也是写了出来。
首先WebRTC,这个可以百度一下,大概就是一个音频和视频通讯技术,可以跨平台,只要能用浏览器的基本都可以使用,当然要你的浏览器支持。但是这东西好像是有规范,但是各个浏览器实现方式有些不一样,我这里主要使用的是chrome做的例子。地址在:http://www.acgist.com/demo/video(如果很长时间没有加载出来,对不起,很可能是你上不了google)。
使用到的javascript都在页面上面都有,注释也差不多写了,我这里也不贴出来了。还有就是引用了google的js库:channel.js。不过还是下载下来放到本地服务器吧,因为很多地方访问google.com很吃力啊。最开始就是这个js没有加载完郁闷了很久,还一直以为是代码写错了。
另外在进入页面的时候,注意初始化页面js中的一个参数:initiator:如果是创建人这个参数设为false;如果是加入的时候这个设置为true。为true的时候,才会发起视频通话的请求
这里我主要贴一下服务端的代码,其实服务端代码很简单,就是收到用户的请求,发送给另外一个用户就可以了,这里处理的其实是用户WebRTC的一些信息,并不是去传输视频,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/acgist.video/{uid}")
public class AcgistVideo {
// 最大通话数量
private static final int MAX_COUNT = 20;
private static final long MAX_TIME_OUT = 2 * 60 * 1000;
// 用户和用户的对话映射
private static final Map<String, String> user_user = Collections.synchronizedMap(new HashMap<String, String>());
// 用户和websocket的session映射
private static final Map<String, Session> sessions = Collections.synchronizedMap(new HashMap<String, Session>());
/**
* 打开websocket
* @param session websocket的session
* @param uid 打开用户的UID
*/
@OnOpen
public void onOpen(Session session, @PathParam("uid")String uid) {
session.setMaxIdleTimeout(MAX_TIME_OUT);
sessions.put(uid, session);
}
/**
* websocket关闭
* @param session 关闭的session
* @param uid 关闭的用户标识
*/
@OnClose
public void onClose(Session session, @PathParam("uid")String uid) {
remove(session, uid);
}
/**
* 收到消息
* @param message 消息内容
* @param session 发送消息的session
* @param uid
*/
@OnMessage
public void onMessage(String message, Session session, @PathParam("uid")String uid) {
try {
if(uid != null && user_user.get(uid) != null && AcgistVideo.sessions.get(user_user.get(uid)) != null) {
Session osession = sessions.get(user_user.get(uid)); // 被呼叫的session
if(osession.isOpen())
osession.getAsyncRemote().sendText(new String(message.getBytes("utf-8")));
else
this.nowaiting(osession);
} else {
this.nowaiting(session);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 没有人在等待
* @param session 发送消息的session
*/
private void nowaiting(Session session) {
session.getAsyncRemote().sendText("{\"type\" : \"nowaiting\"}");
}
/**
* 是否可以继续创建通话房间
* @return 可以:true;不可以false;
*/
public static boolean canCreate() {
return sessions.size() <= MAX_COUNT;
}
/**
* 判断是否可以加入
* @param oid 被申请对话的ID
* @return 如果能加入返回:true;否则返回false;
*/
public static boolean canJoin(String oid) {
return !(oid != null && user_user.containsKey(oid) && user_user.get(oid) != null);
}
/**
* 添加视频对象
* @param uid 申请对话的ID
* @param oid 被申请对话的ID
* @return 是否是创建者:如果没有申请对话ID为创建者,否则为为加入者。创建者返回:true;加入者返回:false;
*/
public static boolean addUser(String uid, String oid) {
if(oid != null && !oid.isEmpty()) {
AcgistVideo.user_user.put(uid, oid);
AcgistVideo.user_user.put(oid, uid);
return false;
} else {
AcgistVideo.user_user.put(uid, null);
return true;
}
}
/**
* 移除聊天用户
* @param session 移除的session
* @param uid 移除的UID
*/
private static void remove(Session session, String uid) {
String oid = user_user.get(uid);
if(oid != null) user_user.put(oid, null); // 设置对方无人聊天
sessions.remove(uid); // 异常session
user_user.remove(uid); // 移除自己
try {
if(session != null && session.isOpen()) session.close(); // 关闭session
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
上面最主要的就是onMessage方法,其他很多都是一些辅助方法。注意这个需要使用到javaEE7的新内容,所以服务器请使用tomcat8。
例子下载:http://pan.baidu.com/s/1mgFkXHe
参考文章:http://blog.csdn.net/leecho571/article/details/8146525
这个是国外的一个例子(功能比较多):https://talky.io/
下面是截图(不要吐槽看不清楚啊,是上传那里压缩图片写的不好):
注:有时候会断开连接,大概是STUN服务器连接不上吧。