基于java webRct webSocket 实现点对点视频 (需要源码的请加支付宝好友)
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
String ctx = request.getContextPath() + "/";
pageContext.setAttribute("ctx", ctx);
%>
<html>
<head>
<link rel="canonical" href="${roomLink}" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<script src="./js/channel.js"></script>
<!-- type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
-->
<style type="text/css">
a:link {
color: #ffffff;
} a:visited {
color: #ffffff;
} html,body {
background-color: #000000;
height: 100%;
font-family: Verdana, Arial, Helvetica, sans-serif;
} body {
margin: 0;
padding: 0;
} #container {
background-color: #000000;
position: relative;
min-height: 100%;
width: 100%;
margin: 0px auto;
-webkit-perspective: 1000;
} #card {
-webkit-transition-property: rotation;
-webkit-transition-duration: 2s;
-webkit-transform-style: preserve-3d;
} #local {
position: absolute;
width: 100%;
-webkit-transform: scale(-1, 1);
-webkit-backface-visibility: hidden;
} #remote {
position: absolute;
width: 100%;
-webkit-transform: rotateY(180deg);
-webkit-backface-visibility: hidden;
} #mini {
position: absolute;
height: 30%;
width: 30%;
bottom: 32px;
right: 4px;
-webkit-transform: scale(-1, 1);
opacity: 1.0;
} #localVideo {
opacity: 0;
-webkit-transition-property: opacity;
-webkit-transition-duration: 2s;
} #remoteVideo {
opacity: 0;
-webkit-transition-property: opacity;
-webkit-transition-duration: 2s;
} #miniVideo {
opacity: 0;
-webkit-transition-property: opacity;
-webkit-transition-duration: 2s;
} #footer {
spacing: 4px;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
background-color: #3F3F3F;
color: rgb(255, 255, 255);
font-size: 13px;
font-weight: bold;
line-height: 28px;
text-align: center;
} #hangup {
font-size: 13px;
font-weight: bold;
color: #FFFFFF;
width: 128px;
height: 24px;
background-color: #808080;
border-style: solid;
border-color: #FFFFFF;
margin: 2px;
} #logo {
display: block;
top: 4;
right: 4;
position: absolute;
float: right;
opacity: 0.5;
}
</style>
</head>
<body>
<script type="text/javascript">
var localVideo;
var miniVideo;
var remoteVideo;
var localStream;
var remoteStream;
var channel;
var channelReady = false;
var pc;
var socket;
var footer;
var initiator = ${initiator};
var started = false;
var isRTCPeerConnection = true;
var mediaConstraints = {
'mandatory':{
'OfferToReceiveAudio' : true,
'OfferToReceiveVideo' : true
}
};
var isVideoMuted = false;
var isAudioMuted = false;
var URL;
function initialize() {
console.log("Initializing; room=${roomKey}.");
card = document.getElementById("card");
localVideo = document.getElementById("localVideo");
footer = document.getElementById("footer");
miniVideo = document.getElementById("miniVideo");
remoteVideo = document.getElementById("remoteVideo");
resetStatus();
openChannel();
getUserMedia();
console.log("initialize1");
URL = (window.URL || window.webkitURL || window.msURL || window.oURL);
} function getUserMedia() {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
// if(navigator.getUserMedia){
try {
// navigator.webkitGetUserMedia({
navigator.getUserMedia({
"audio": true,
"video": true
}, onUserMediaSuccess, onUserMediaError);
console.log("Requested access to local media with new syntax.");
} catch (e) {
try {
navigator.getUserMedia("video,audio",onUserMediaSuccess, onUserMediaError);
console.log("Requested access to local media with old syntax.");
} catch (e) {
alert("webkitGetUserMedia() failed. Is the MediaStream flag enabled in about:flags?");
console.log("webkitGetUserMedia failed with exception: "+ e.message);
}
}
console.log("getUserMedia2");
}
// } function onUserMediaSuccess(stream) {
console.log("User has granted access to local media.");
// var url = webkitURL.createObjectURL(stream);
var url = URL.createObjectURL(stream);
localVideo.style.opacity = 1;
localVideo.src = url;
localStream = stream;
// Caller creates PeerConnection.
if (initiator)
maybeStart(); console.log("onUserMediaSuccess3");
} function maybeStart() {
if (!started && localStream && channelReady) {
setStatus("连接中...");
console.log("Creating PeerConnection.");
createPeerConnection();
console.log("Adding local stream.");
pc.addStream(localStream);
started = true;
// Caller initiates offer to peer.
if (initiator)
doCall();
}
console.log("maybeStart4");
} function doCall() {
console.log("Sending offer to peer.");
if (isRTCPeerConnection) {
pc.createOffer(setLocalAndSendMessage, null, mediaConstraints);
// pc.createOffer(setLocalAndSendMessage,function (error) {
// console.log('Failure callback: ' + error);
// });
} else {
var offer = pc.createOffer(mediaConstraints);
pc.setLocalDescription(pc.SDP_OFFER, offer);
sendMessage({
type : 'offer',
sdp : offer.toSdp()
});
pc.startIce();
}
console.log("doCall5");
} function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
console.log("setLocalAndSendMessage6");
} function sendMessage(message) {
var msgString = JSON.stringify(message);
console.log('发出信息 : ' + msgString);
path = 'message?r=${roomKey}' + '&u=${user}';
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send(msgString);
console.log("sendMessage7");
} function openChannel() {
console.log("Opening channel.");
socket = new WebSocket("ws://"+window.location.host+"${ctx}websocket?u=${user}");
// socket = new WebSocket("ws://10.74.0.154:8080");
socket.onopen = onChannelOpened;
socket.onmessage = onChannelMessage;
socket.onclose = onChannelClosed;
console.log("openChannel8");
} function resetStatus() {
if (!initiator) {
setStatus("让别人加入视频聊天: <a href=\"${roomLink}\">${roomLink}</a>");
} else {
setStatus("初始化...");
}
console.log("resetStatus9");
} function createPeerConnection() {
console.log("createPeerConnection9");
var pc_config = {
"iceServers" : [ {
"url" : "stun:stun.l.google.com:19302"
} ]
};
try {
pc = new webkitRTCPeerConnection(pc_config); pc.onicecandidate = onIceCandidate;
console.log("Created webkitRTCPeerConnnection with config \""
+ JSON.stringify(pc_config) + "\".");
} catch (e) {
try {
var stun_server = "";
if (pc_config.iceServers.length !== 0) {
stun_server = pc_config.iceServers[0].url.replace(
'stun:', 'STUN ');
}
pc = new webkitPeerConnection00(stun_server,
onIceCandidate00);
isRTCPeerConnection = false;
console.log("Created webkitPeerConnnection00 with config \""
+ stun_server + "\".");
} catch (e) {
console.log("Failed to create PeerConnection, exception: "
+ e.message);
alert("Cannot create PeerConnection object; Is the 'PeerConnection' flag enabled in about:flags?");
return;
}
} pc.onconnecting = onSessionConnecting;
pc.onopen = onSessionOpened;
pc.onaddstream = onRemoteStreamAdded;
pc.onremovestream = onRemoteStreamRemoved;
} function setStatus(state) {
footer.innerHTML = state;
console.log("setStatus10");
} function doAnswer() {
console.log("doAnswer11");
console.log("Sending answer to peer.");
if (isRTCPeerConnection) {
pc.createAnswer(setLocalAndSendMessage,null,mediaConstraints);
// pc.createAnswer(setLocalAndSendMessage,function (error) {
// console.log('Failure callback: ' + error);
// });
} else {
var offer = pc.remoteDescription;
var answer = pc.createAnswer(offer.toSdp(), mediaConstraints);
pc.setLocalDescription(pc.SDP_ANSWER, answer);
sendMessage({
type : 'answer',
sdp : answer.toSdp()
});
pc.startIce();
}
} function processSignalingMessage00(message) {
console.log("processSignalingMessage0012");
var msg = JSON.parse(message); // if (msg.type == 'offer') should not happen here.
if (msg.type == 'answer' && started) {
pc.setRemoteDescription(pc.SDP_ANSWER, new SessionDescription(
msg.sdp));
} else if (msg.type == 'candidate' && started) {
var candidate = new IceCandidate(msg.label, msg.candidate);
pc.processIceMessage(candidate);
} else if (msg.type == 'bye' && started) {
onRemoteHangup();
}
} var channelOpenTime;
var channelCloseTime; function onChannelOpened() {
console.log("onChannelOpened13");
channelOpenTime = new Date();
console.log("Channel opened.Open time is : "
+ channelOpenTime.toLocaleString());
channelReady = true;
if (initiator)
maybeStart();
}
function onChannelMessage(message) {
console.log("onChannelMessage14");
console.log('收到信息 : ' + message.data);
if (isRTCPeerConnection)
processSignalingMessage(message.data);//建立视频连接
else
processSignalingMessage00(message.data);
} function processSignalingMessage(message) {
console.log("processSignalingMessage15");
var msg = JSON.parse(message);
console.log("msg.type:"+msg.type);
if (msg.type == 'offer') {
// Callee creates PeerConnection
if (!initiator && !started)
maybeStart(); // We only know JSEP version after createPeerConnection().
if (isRTCPeerConnection)
pc.setRemoteDescription(new RTCSessionDescription(msg));
else
pc.setRemoteDescription(pc.SDP_OFFER,new SessionDescription(msg.sdp)); doAnswer();
} else if (msg.type == 'answer' && started) {
pc.setRemoteDescription(new RTCSessionDescription(msg));
} else if (msg.type == 'candidate' && started) {
var nativeRTCIceCandidate = (window.mozRTCIceCandidate || window.RTCIceCandidate);
var candidate = new nativeRTCIceCandidate({
sdpMLineIndex : msg.label,
candidate : msg.candidate
});
pc.addIceCandidate(candidate);
} else if (msg.type == 'bye' && started) {
onRemoteHangup();
}
} function onChannelError() {
console.log('Channel error.16');
}
function onChannelClosed() {
console.log('onChannelClosed.17');
if(!channelOpenTime){
channelOpenTime = new Date();
}
channelCloseTime = new Date();
console.log("Channel closed.Close time is "
+ channelOpenTime.toLocaleString()
+ " ,Keep time : "
+ ((channelCloseTime.getTime() - channelOpenTime
.getTime()) / 1000 + "s"));
openChannel();
} function onUserMediaError(error) {
console.log('onUserMediaError.18');
console.log("Failed to get access to local media. Error code was "+ error.code);
alert("Failed to get access to local media. Error code was "+ error.code + ".");
} function onIceCandidate(event) {
console.log('onIceCandidate.19');
if (event.candidate) {
sendMessage({
type : 'candidate',
label : event.candidate.sdpMLineIndex,
id : event.candidate.sdpMid,
candidate : event.candidate.candidate
});
} else {
console.log("End of candidates.");
}
} function onIceCandidate00(candidate, moreToFollow) {
console.log('onIceCandidate00.20');
if (candidate) {
sendMessage({
type : 'candidate',
label : candidate.label,
candidate : candidate.toSdp()
});
} if (!moreToFollow) {
console.log("End of candidates.");
}
} function onSessionConnecting(message) {
console.log('onSessionConnecting.21');
console.log("Session connecting.");
}
function onSessionOpened(message) {
console.log('onSessionConnecting.22');
console.log("Session opened.");
} function onRemoteStreamAdded(event) {
console.log('onRemoteStreamAdded.23');
console.log("Remote stream added.");
console.log("输出远程流"+event.stream);
// var url = webkitURL.createObjectURL(event.stream);
var url = URL.createObjectURL(event.stream);
miniVideo.src = localVideo.src;
remoteVideo.src = url;
console.log(url+"www.baidu.com");
remoteStream = event.stream; waitForRemoteVideo();
}
function onRemoteStreamRemoved(event) {
console.log('onRemoteStreamAdded.24');
console.log("Remote stream removed.");
} function onHangup() {
console.log('onHangup.25');
console.log("Hanging up.");
transitionToDone();
stop();
socket.close(); } function onRemoteHangup() {
console.log('onRemoteHangup.26');
console.log('Session terminated.');
transitionToWaiting();
stop();
initiator = 0;
} function stop() {
console.log('stop.27');
started = false;
isRTCPeerConnection = true;
isAudioMuted = false;
isVideoMuted = false;
pc.close();
pc = null;
} function waitForRemoteVideo() {
console.log('waitForRemoteVideo.28');
console.log("videoTracks:"+remoteStream.getVideoTracks().length);
console.log("remoteVideo.currentTime:"+remoteVideo.currentTime);
// console.log("remoteStream.videoTracks.length:"+remoteStream.videoTracks.length);
if (remoteStream.getVideoTracks().length == 1 || remoteVideo.currentTime > 0) {
transitionToActive();
} else {
setTimeout(waitForRemoteVideo, 100);
}
}
function transitionToActive() {
console.log('transitionToActive.29');
remoteVideo.style.opacity = 1;
card.style.webkitTransform = "rotateY(180deg)";
setTimeout(function() {
localVideo.src = "";
}, 500);
setTimeout(function() {
miniVideo.style.opacity = 1;
}, 1000);
setStatus("<input type=\"button\" id=\"hangup\" value=\"Hang up\" onclick=\"onHangup()\" />");
}
function transitionToWaiting() {
console.log('transitionToWaiting.30');
card.style.webkitTransform = "rotateY(0deg)";
setTimeout(function() {
localVideo.src = miniVideo.src;
miniVideo.src = "";
remoteVideo.src = ""
}, 500);
miniVideo.style.opacity = 0;
remoteVideo.style.opacity = 0;
resetStatus();
}
function transitionToDone() {
console.log('transitionToDone.31');
localVideo.style.opacity = 0;
remoteVideo.style.opacity = 0;
miniVideo.style.opacity = 0;
setStatus("You have left the call. <a href=\"{{ room_link }}\">Click here</a> to rejoin.");
}
function enterFullScreen() {
console.log('enterFullScreen.32');
container.webkitRequestFullScreen();
} function toggleVideoMute() {
console.log('toggleVideoMute.33');
if (localStream.getVideoTracks().length == 0) {
console.log("No local video available.");
return;
} if (isVideoMuted) {
for (i = 0; i < localStream.getVideoTracks().length; i++) {
localStream.getVideoTracks[i].enabled = true;
}
console.log("Video unmuted.");
} else {
for (i = 0; i < localStream.getVideoTracks().length; i++) {
localStream.getVideoTracks[i].enabled = false;
}
console.log("Video muted.");
} isVideoMuted = !isVideoMuted;
} function toggleAudioMute() {
console.log("toggleAudioMute34");
if (localStream.getAudioTracks().length == 0) {
console.log("No local audio available.");
return;
} if (isAudioMuted) {
for (i = 0; i < localStream.getAudioTracks().length; i++) {
localStream.audioTracks[i].enabled = true;
}
console.log("Audio unmuted.");
} else {
for (i = 0; i < localStream.getAudioTracks().length; i++) {
localStream.getAudioTracks()[i].enabled = false;
}
console.log("Audio muted.");
} isAudioMuted = !isAudioMuted;
} setTimeout(initialize, 1); // Send BYE on refreshing(or leaving) a demo page
// to ensure the room is cleaned for next session.
window.onbeforeunload = function() {
sendMessage({
type : 'bye'
});
} // Ctrl-D: toggle audio mute; Ctrl-E: toggle video mute.
// On Mac, Command key is instead of Ctrl.
// Return false to screen out original Chrome shortcuts.
document.onkeydown = function() {
if (navigator.appVersion.indexOf("Mac") != -1) {
if (event.metaKey && event.keyCode == 68) {
toggleAudioMute();
return false;
}
if (event.metaKey && event.keyCode == 69) {
toggleVideoMute();
return false;
}
} else {
if (event.ctrlKey && event.keyCode == 68) {
toggleAudioMute();
return false;
}
if (event.ctrlKey && event.keyCode == 69) {
toggleVideoMute();
return false;
}
}
}
</script>
<div id="container" ondblclick="enterFullScreen()">
<div id="card">
<div id="local">
<video width="100%" height="100%" id="localVideo"
autoplay="autoplay" />
</div>
<div id="remote">
<video width="100%" height="100%" id="remoteVideo"
autoplay="autoplay"> </video>
<div id="mini">
<video width="100%" height="100%" id="miniVideo" autoplay="autoplay" />
</div>
</div>
</div>
<div id="footer"></div>
<a href="http://www.webrtc.org"> <img id="logo" alt="WebRTC"
src="${ctx}images/webrtc_black_20p.png"> </a>
</div>
</body>
</html>
环境必须是jdk1.7,tomcat7才能把项目运行起来,把tomat的lib包下的catalian.jar,tomcat-coyote.jar加入项目中
package org.rtc.servlet; import java.io.IOException;
import java.util.UUID; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils;
import org.rtc.room.WebRTCRoomManager; @WebServlet(urlPatterns = {"/room"})
public class WebRTCRoomServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String r = request.getParameter("r");
if(StringUtils.isEmpty(r)){
//如果房间为空,则生成一个新的房间号
r = String.valueOf(System.currentTimeMillis());
response.sendRedirect("room?r=" + r);
}else{
Integer initiator = 1;
String user = UUID.randomUUID().toString().replace("-", "");//生成一个用户ID串
if(!WebRTCRoomManager.haveUser(r)){//第一次进入可能是没有人的,所以就要等待连接,如果有人进入了带这个房间好的页面就会发起视频通话的连接
initiator = 0;//如果房间没有人则不发送连接的请求
}
WebRTCRoomManager.addUser(r, user);//向房间中添加一个用户
String roomLink = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() + request.getContextPath() +"/room?r=" + r;
String roomKey = r;//设置一些变量
request.setAttribute("initiator", initiator);
request.setAttribute("roomLink", roomLink);
request.setAttribute("roomKey", roomKey);
request.setAttribute("user", user);
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
}
package org.rtc.servlet; import java.io.BufferedReader;
import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils;
import org.rtc.room.WebRTCRoomManager;
import org.rtc.websocket.WebRTCMessageInboundPool; import net.sf.json.JSONObject; @WebServlet(urlPatterns = {"/message"})
public class WebRTCMessageServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
super.doPost(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String r = request.getParameter("r");//房间号
String u = request.getParameter("u");//通话人
BufferedReader br = request.getReader();
String line = null;
StringBuilder sb = new StringBuilder();
while((line = br.readLine())!=null){
sb.append(line); //获取输入流,主要是视频定位的信息
} String message = sb.toString();
JSONObject json = JSONObject.fromObject(message);
if (json != null) {
String type = json.getString("type");
if ("bye".equals(type)) {//客户端退出视频聊天
System.out.println("user :" + u + " exit..");
if(StringUtils.isNotEmpty(r)){
WebRTCRoomManager.removeUser(r, u);
}else{
System.out.println("没有该房间号");
}
package org.rtc.servlet; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.rtc.websocket.WebRTCMessageInbound;
@WebServlet(urlPatterns = { "/websocket"})
public class WebRTCWebSocketServlet extends WebSocketServlet { private static final long serialVersionUID = 1L; private String user; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.user = request.getParameter("u");
super.doGet(request, response);
} @Override
protected StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request) {
return new WebRTCMessageInbound(user);
}
}
package org.rtc.room; import java.util.HashMap;
import java.util.Map; public class WebRTCRoomManager { private static final Map<String,WebRTCSimpleRoom> provider = new HashMap<String,WebRTCSimpleRoom>(); public static void addUser(String roomKey,String user){
WebRTCSimpleRoom room = provider.get(roomKey);
if(room == null){
System.out.println("add room : " + roomKey);
room = new WebRTCSimpleRoom(roomKey,user);
provider.put(roomKey, room);
}else{
room.addUser(user);
}
} public static void removeUser(String roomKey,String user){
WebRTCSimpleRoom room = provider.get(roomKey);
if(room != null){
System.out.println("remove user : " + user);
room.removeUser(user);
}
if(!room.haveUser()){
provider.remove(roomKey);
System.out.println("remove room : " + roomKey);
}
} public static boolean haveUser(String key){
WebRTCSimpleRoom room = provider.get(key);
if(room != null){
return room.haveUser();
}else{
return false;
}
} public static String getOtherUser(String roomKey,String user){
WebRTCSimpleRoom room = provider.get(roomKey);
return room.getOtherUser(user);
}
}
package org.rtc.room; import org.apache.commons.lang.StringUtils; public class WebRTCSimpleRoom { private String key; private String user1; private String user2; public WebRTCSimpleRoom(){ } public WebRTCSimpleRoom(String key,String user1){
this.key = key;
this.user1 = user1;
} /**
* @return the key
*/
public String getKey() {
return key;
} /**
* @param key
* the key to set
*/
public void setKey(String key) {
this.key = key;
} public String getUser1() {
return user1;
} public void setUser1(String user1) {
this.user1 = user1;
} public String getUser2() {
return user2;
} public void setUser2(String user2) {
this.user2 = user2;
} public void addUser(String user) {
if (StringUtils.isEmpty(user1)) {
this.setUser1(user);
} else if (StringUtils.isEmpty(user2)) {
this.setUser2(user);
}
} public void removeUser(String user) {
if (StringUtils.isNotEmpty(user1)) {
if (user1.equals(user)) {
this.setUser1(null);
}
} else if (StringUtils.isNotEmpty(user2)) {
if (user2.equals(user)) {
this.setUser2(null);
}
}
} public boolean haveUser() {
return !(this.getUser1() == null && this.getUser2() == null);
} public String getOtherUser(String user){
if(user.equals(user1)){
return user2;
}else{
return user1;
}
}
}
package org.rtc.websocket; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer; import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound; public class WebRTCMessageInbound extends MessageInbound { private final String user; public WebRTCMessageInbound(String user) {
this.user = user;
} public String getUser(){
return this.user;
} @Override
protected void onOpen(WsOutbound outbound) {
//触发连接事件,在连接池中添加连接
WebRTCMessageInboundPool.addMessageInbound(this);
} @Override
protected void onClose(int status) {
//触发关闭事件,在连接池中移除连接
WebRTCMessageInboundPool.removeMessageInbound(this);
} @Override
protected void onBinaryMessage(ByteBuffer message) throws IOException {
throw new UnsupportedOperationException(
"Binary message not supported.");
} @Override
protected void onTextMessage(CharBuffer message) throws IOException { }
}
package org.rtc.websocket; import java.io.IOException;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map; public class WebRTCMessageInboundPool { private static final Map<String,WebRTCMessageInbound > connections = new HashMap<String,WebRTCMessageInbound>(); public static void addMessageInbound(WebRTCMessageInbound inbound){
//添加连接
System.out.println("user : " + inbound.getUser() + " join..");
connections.put(inbound.getUser(), inbound);
} public static void removeMessageInbound(WebRTCMessageInbound inbound){
//移除连接
System.out.println("user : " + inbound.getUser() + " exit..");
connections.remove(inbound.getUser());
} public static void sendMessage(String user,String message){
try {
//向特定的用户发送数据
System.out.println("send message to user : " + user + " ,message content : " + message);
WebRTCMessageInbound inbound = connections.get(user);
if(inbound != null){
inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(message));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
String otherUser = WebRTCRoomManager.getOtherUser(r, u);//获取通话的对象
if (u.equals(otherUser)) {
message = message.replace("\"offer\"", "\"answer\"");
message = message.replace("a=crypto:0 AES_CM_128_HMAC_SHA1_32",
"a=xrypto:0 AES_CM_128_HMAC_SHA1_32");
message = message.replace("a=ice-options:google-ice\\r\\n", "");
}
//向对方发送连接数据
WebRTCMessageInboundPool.sendMessage(otherUser, message);
}
}
可以新建一个web项目部署一下试试。
基于java webRct webSocket 实现点对点视频 (需要源码的请加支付宝好友)的更多相关文章
- 基于Java的WebSocket推送
WebSocket的主动推送 关于消息推送,现在的解决方案如轮询.长连接或者短连接,当然还有其他的一些技术框架,有的是客户端直接去服务端拿数据. 其实推送推送主要讲的是一个推的概念,WebSocket ...
- 近200篇机器学习&深度学习资料分享(含各种文档,视频,源码等)(1)
原文:http://developer.51cto.com/art/201501/464174.htm 编者按:本文收集了百来篇关于机器学习和深度学习的资料,含各种文档,视频,源码等.而且原文也会不定 ...
- Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 06 Stack详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 05 Vector详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- 视频直播源码开发中的流媒体协议:rtmp协议
一.概念与摘要 视频直播源码的RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似 ...
- Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
随机推荐
- tensorFlow入门实践(一)
首先应用TensorFlow完成一个线性回归,了解TensorFlow的数据类型和运行机制. import tensorflow as tf import numpy as np import mat ...
- jmeter下载和配置
一.下载 1.进入官网:http://jmeter.apache.org/ 3.环境变量相关配置 电脑桌面---->“计算机”图标---->鼠标右键选择“属性”---->点击高级系统 ...
- 2018-2019-2 网络对抗技术 20165326 Exp3 免杀原理与实践
免杀原理与实践 目录 知识点问答 实践内容 遇到的问题 心得体会 知识点 meterpreter免杀 基础问题回答 杀软是如何检测出恶意代码的? 特征码(基于签名):模式匹配,比对特征码库 启发式:通 ...
- GitHub网站使用的基础入门
github基本入门,首先需要掌握一些ssh非对称加密的知识和一些基本的git命令操作.下面是我推荐的两个比较好的网站,然后我再专门对GitHub网站使用进行步骤讲解. git 命令:http://b ...
- vimrc配置
"=========================================================================" DesCRiption 适合 ...
- Qt + VS2013
参考文章: https://blog.csdn.net/u013447988/article/details/76170070
- django websocket
1.dwebsocket 2.等框架都是错误的 3. django/channels 才是正确姿势 555 4. pip install -U channels 完成后,您应该添加channels到 ...
- Ajax的分析
I.what is Ajax? Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术. A ...
- String为什么是final类型的
String的源码如下: public final class String implements Serializable, Comparable<String>, CharSequen ...
- Shell编程(2)
1 (1) (2) (3) 一.二都是显示数组所有元素,*是作为一个长字符串输出,@是作为数组一个一个输出 三.四都是输出数组的长度 五.六都是输出数组中第一个元素的长度 (4) unset是name ...