webrtc 实时视频 .net websocket信令服务器

时间:2022-09-16 14:48:50

这篇文章主要参考了 Webrtc WebSocket实现音视频通讯,非常感谢提供代码

前端部分完全是从这篇文章复制过来的,只是修改了webscket的url,还有加入了webrtc-adapterjs,至于做什么,可以点击链接进行了解

前端代码部分(主要来自开头提及的博文)

<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
Welcome<br/><input id="text" type="text" />
<button onclick="send()">发送消息</button>
<hr/>
<button onclick="closeWebSocket()">关闭WebSocket连接</button>
<hr/>
<div id="message"></div> <video id="vid1" width="320" height="240" autoplay></video>
<video id="vid2" width="320" height="240" autoplay></video><br>
<a id="create" href="webrtc.html#true" onclick="init()">点击此链接新建聊天室</a><br>
<p id="tips" style="background-color:red">请在其他浏览器中打开:http://此电脑 加入此视频聊天</p> <script type="text/javascript" src="http://cdn.staticfile.org/webrtc-adapter/zv4.1.1/adapter.min.js"></script>
<script type="text/javascript">
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia; var isCaller = window.location.href.split('#')[1];
var websocket = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window) {
websocket = new WebSocket("ws://192.168.31.175:8181");
} else {
alert('当前浏览器 Not support websocket')
} //连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("WebSocket连接发生错误");
}; //连接成功建立的回调方法
websocket.onopen = function() {
setMessageInnerHTML("WebSocket连接成功");
} // 创建PeerConnection实例 (参数为null则没有iceserver,即使没有stunserver和turnserver,仍可在局域网下通讯)
var pc = new window.RTCPeerConnection(null); // 发送ICE候选到其他客户端
pc.onicecandidate = function(event) {
setMessageInnerHTML("我看看 1");
if(event.candidate !== null) {
setMessageInnerHTML("我看看 2");
websocket.send(JSON.stringify({
"event": "_ice_candidate",
"data": {
"candidate": event.candidate
}
}));
}
}; //接收到消息的回调方法
websocket.onmessage = function(event) {
setMessageInnerHTML("接收到的信息");
setMessageInnerHTML(event.data);
if(event.data == "new user") {
console.log("new user");
location.reload();
} else {
var json = JSON.parse(event.data);
console.log('onmessage: ', json);
//如果是一个ICE的候选,则将其加入到PeerConnection中,否则设定对方的session描述为传递过来的描述
if(json.event === "_ice_candidate") {
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
// 如果是一个offer,那么需要回复一个answer
if(json.event === "_offer") {
pc.createAnswer(sendAnswerFn, function(error) {
console.log('Failure callback: ' + error);
});
}
}
}
} //连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("WebSocket连接关闭");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
closeWebSocket();
} //将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
} //关闭WebSocket连接
function closeWebSocket() {
websocket.close();
} //发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
} // stun和turn服务器
var iceServer = {
"iceServers": [{
"url": "stun:stunserver.org"
}, {
"url": "turn:numb.viagenie.ca",
"username": "webrtc@live.com",
"credential": "muazkh"
}]
}; // 如果检测到媒体流连接到本地,将其绑定到一个video标签上输出
pc.onaddstream = function(event) {
document.getElementById('vid2').src = URL.createObjectURL(event.stream);
}; // 发送offer和answer的函数,发送本地session描述
var sendOfferFn = function(desc) {
pc.setLocalDescription(desc);
websocket.send(JSON.stringify({
"event": "_offer",
"data": {
"sdp": desc
}
}));
},
sendAnswerFn = function(desc) {
pc.setLocalDescription(desc);
websocket.send(JSON.stringify({
"event": "_answer",
"data": {
"sdp": desc
}
}));
}; // 获取本地音频和视频流
navigator.getUserMedia({
"audio": true,
"video": true
},
function(stream) {
//绑定本地媒体流到video标签用于输出
document.getElementById('vid1').src = URL.createObjectURL(stream);
document.getElementById('vid1').muted = true;
//向PeerConnection中加入需要发送的流
pc.addStream(stream);
//如果是发起方则发送一个offer信令
if(isCaller) {
pc.createOffer(sendOfferFn, function(error) {
console.log('Failure callback: ' + error);
});
}
},
function(error) {
//处理媒体流创建失败错误
console.log('getUserMedia error: ' + error);
}); window.onload = function() {
if(isCaller == null || isCaller == undefined) {
var tips = document.getElementById("tips");
tips.remove();
} else {
var create = document.getElementById("create");
create.remove();
}
}; function init() {
location.reload();
}
</script> </body> </html>

提及博文的java部分,我用了.net 控制台程序简单实现了一个,相当于一个极简的信令服务器吧(Fleck 可以在vs的管理nuget程序包中获得)

static void Main(string[] args)
{
//客户端url以及其对应的Socket对象字典
IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>(); var server = new WebSocketServer("ws://192.168.31.175:8181"); //出错后重启
server.RestartAfterListenError = true; server.Start(socket =>
{
socket.OnOpen = () => {
//获取客户端网页的url
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
dic_Sockets.Add(clientUrl, socket);
Console.WriteLine(DateTime.Now.ToString() + "|服务器:和客户端网页:" + clientUrl + " 建立WebSock连接!"); };
socket.OnClose = () => //连接关闭事件
{
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
//如果存在这个客户端,那么对这个socket进行移除
if (dic_Sockets.ContainsKey(clientUrl))
{
//注:Fleck中有释放
//关闭对象连接
//if (dic_Sockets[clientUrl] != null)
//{
//dic_Sockets[clientUrl].Close();
//}
dic_Sockets.Remove(clientUrl);
}
Console.WriteLine(DateTime.Now.ToString() + "|服务器:和客户端网页:" + clientUrl + " 断开WebSock连接!");
};
socket.OnMessage = message => //接受客户端网页消息事件
{
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
foreach (var item in dic_Sockets.Where(a=>a.Key!=clientUrl))
{
item.Value.Send(message);
}
//Console.WriteLine(DateTime.Now.ToString() + "|服务器:【收到】来客户端网页:" + clientUrl + "的信息:\n" + message);
};
socket.OnBinary = b => { };
}); Console.ReadKey();
}

记录完毕,这个东西仅仅只是个demo,可以拿来玩一下