我的网络聊天代码存在问题。我不能在同伴之间建立联系。 PC1通过信号服务器发送报价请求,pc2添加候选,但pc2不能发送候选人并回答pc1,为什么?
我找不到多个小时的错误,请帮我建立webrtc连接。
app.js
var app = require('express')();
var server = require('http').createServer(app);
var virtualDirPath = process.env.virtualDirPath || '';
var io = require('socket.io')(server)//(server, { path: virtualDirPath + '/socket.io' });
var users = {};
server.listen(process.env.PORT || 8080, function () {
console.log('Подняли сервер на *:8080');
});
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/style.css', function (req, res) {
res.sendFile(__dirname + '/style.css');
});
app.get('/index.js', function (req, res) {
res.sendFile(__dirname + '/index.js');
});
io.on('connection', function (socket) {
socket.on('login', function(data){
console.log('Зашел пользователь:', data.name);
//Не даем подключиться если пользователь уже в чате
if(users[data.name]) {
socket.emit('login', {state: 'taken'});
}else{
socket.name = data.name;
users[data.name] = socket;
socket.broadcast.emit('newuser', {name: data.name});
socket.emit('login', {name: data.name});
}
});
//format offer
socket.on('offer', function(data){//data.name, data.localDescription
console.log('Поулчили offer для:', data.to);
users[data.to].emit("offer", data);
});
socket.on('answer', function(data){//data.name, data.localDescription
console.log('Поулчили answer для:', data.to);
console.log(data);
users[data.to].emit("offer", data);
});
socket.on('candidate', function(data){//data.name, data.candidate
console.log('Поулчили candidate для:', data.to);
users[data.to].emit("candidate", data);
});
socket.on('disconnect', function (data) {
console.log(data);
io.emit('user disconnected',data.to);
io.sockets.emit('quit', {name: data.from})
delete users[data.from];
});
});
的index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="modal fade" id="login-modal" tabindex="-1" role="dialog" data-keyboard="false" data-backdrop="static" aria-hidden="true" style="display: none;">
<div class="modal-dialog">
<div class="loginmodal-container">
<h1>Войдите в чат</h1><br>
<form id="loginForm">
<input type="text" name="username" placeholder="Username">
<input type="submit" id="login" class="login loginmodal-submit" value="Вход">
</form>
</div>
</div>
</div>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js:
var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
var socket;
var peers = {};
var server = {
iceServers: [
{url: "stun:23.21.150.121"},
{url: "stun:stun.l.google.com:19302"}
]
};
var options = {
optional: [
{DtlsSrtpKeyAgreement: true}, // требуется для соединения между Chrome и Firefox
{RtpDataChannels: true} // требуется в Firefox для использования DataChannels API
]
}
$(document).ready(function () {
$('#login-modal').modal('show');
//Логинимся.
$('#loginForm').on('submit', function(e) {
e.preventDefault();
var name = $('input[name=username]').val();
if (!name) {
alert('Вы не ввели логин');
return;
}else{
//подключаемся к сигнальному серверу
socket = io.connect(':8080', {
forceNew: true
});
socket.emit('login',{name: name})
}
socket.on('login', function(data){
var current_name = data.name;
if(data.state === 'taken'){
alert('Пльзователь с таким ником уже находится в чате');
}else if(data.name != undefined){
console.log('Успешно зашли в чат');
socket.on('newuser', function(data){
console.log('receive newuser ', data.name);
peers[data.name] = {
cache: []
};
// Создаем новое подключение
var pc = new PeerConnection(server, options);
// Инициализируем его
initConn(pc, data.name, current_name, "offer");
// Сохраняем пир в списке
peers[data.name].connection = pc;
// Создаем DataChannel по которому и будет происходить обмен сообщениями
var channel = pc.createDataChannel("chatchannel", {});
channel.owner = data.name;
peers[data.name].channel = channel;
// Устанавливаем обработчики событий канала
bindEvents(channel);
// Создаем SDP offer
pc.createOffer(function(offer) {
console.log('Установили локальный дескрипшен');
pc.setLocalDescription(offer);
},function(err){
console.log(err);
});
});
socket.on('candidate', function(data){
console.log('receive candidate from ', data.from);
createConnection(data.from, current_name);
var pc = peers[data.from].connection;
console.log(data.candidate);
pc.addIceCandidate(new IceCandidate(data.candidate));
});
socket.on('offer', function(data){ //name,localDescription
console.log('receive offer from ', data.from);
createConnection(data.from, current_name);
var pc = peers[data.from].connection;
console.log(pc);
pc.setRemoteDescription(new SessionDescription(data.localDescription));
pc.createAnswer(function(answer) {
pc.setLocalDescription(answer);
console.log('answer created');
},function(err){
console.log(err);
});
});
socket.on('answer', function(data){
console.log('receive answer from ', data.from);
var pc = peers[data.name].connection;
pc.setRemoteDescription(new SessionDescription(data.localDescription));
});
}else{
alert('Ошибка при логине');
location.reload();
}
});
});
});
function createConnection(name, current_name){
//Инициализируем подключение если его нет
console.log(peers[name])
if (peers[name] === undefined){
peers[name] = {
cache: []
};
var pc = new PeerConnection(server, options);
initConn(pc, name, current_name, 'answer');
peers[name].connection = pc;
pc.ondatachannel = function(e) {
peers[name].channel = e.channel;
peers[name].channel.owner = name;
bindEvents(peers[name].channel);
}
console.log('CreateConnection');
console.log(pc)
}
}
function initConn(pc, name, current_name, sdpType) {
console.log(pc);
console.log('-----------------------------------------')
pc.onicecandidate = function (event) {
if (event.candidate) {
// При обнаружении нового ICE кандидата добавляем его в список для дальнейшей отправки
peers[name].cache.push(event.candidate);
console.log('1');
} else {
// Когда обнаружение кандидатов завершено, обработчик будет вызван еще раз, но без кандидата
// В этом случае мы отправялем пиру сначала SDP offer или SDP answer (в зависимости от SDP запроса)
socket.emit(sdpType, {to: name, from: current_name, localDescription: pc.localDescription});
console.log('init conn');
console.log(name);
console.log(current_name);
console.log(sdpType);
// ...а затем все найденные ранее ICE кандидаты
for (var i = 0; i < peers[name].cache.length; i++) {
socket.emit("candidate", {to: name, from: current_name, candidate: peers[name].cache[i]});
}
}
}
pc.oniceconnectionstatechange = function (event) {
if (pc.iceConnectionState == "disconnected") {
//Пир отключился
//TODO добавить в список пользоавтелей data.name
delete peers[id];
}
}
}
function bindEvents (channel) {
channel.onopen = function () {
//TODO добавить в список пользоавтелей channel.owner
};
channel.onmessage = function (e) {
//TODO add text of message to chat div e.data
};
}
PC2具有localDescription和remoteDescription。 PC2 PeerConnection日志:
RTCPeerConnection {localDescription: RTCSessionDescription, remoteDescription: RTCSessionDescription, signalingState: "stable", iceGatheringState: "new", iceConnectionState: "new"…}
iceConnectionState
:
"new"
iceGatheringState
:
"new"
localDescription
:
RTCSessionDescription
sdp
:
"v=0
↵o=- 4651396889672739307 2 IN IP4 127.0.0.1
↵s=-
↵t=0 0
↵a=msid-semantic: WMS
↵m=application 0 UDP/TLS/RTP/SAVPF 127
↵c=IN IP4 0.0.0.0
↵a=rtcp:9 IN IP4 0.0.0.0
↵a=mid:data
↵a=recvonly
↵a=rtcp-mux
↵a=rtpmap:127 google-data/90000
↵"
type
:
"answer"
__proto__
:
RTCSessionDescription
onaddstream
:
null
ondatachannel
:
(e)
onicecandidate
:
(event)
oniceconnectionstatechange
:
(event)
onnegotiationneeded
:
null
onremovestream
:
null
onsignalingstatechange
:
null
remoteDescription
:
RTCSessionDescription
sdp
:
"v=0
↵o=- 1739995165662969380 2 IN IP4 127.0.0.1
↵s=-
↵t=0 0
↵a=group:BUNDLE data
↵a=msid-semantic: WMS
↵m=application 2740 UDP/TLS/RTP/SAVPF 127
↵c=IN IP4 5.141.232.232
↵b=AS:30
↵a=rtcp:2120 IN IP4 5.141.232.232
↵a=candidate:985767174 1 udp 2113937151 192.168.100.2 58907 typ host generation 0
↵a=candidate:985767174 2 udp 2113937150 192.168.100.2 58909 typ host generation 0
↵a=candidate:842163049 1 udp 1677729535 5.141.232.232 2740 typ srflx raddr 192.168.100.2 rport 58907 generation 0
↵a=candidate:842163049 2 udp 1677729534 5.141.232.232 2120 typ srflx raddr 192.168.100.2 rport 58909 generation 0
↵a=candidate:842163049 2 udp 1677729534 5.141.232.232 2910 typ srflx raddr 192.168.100.2 rport 58909 generation 0
↵a=candidate:842163049 1 udp 1677729535 5.141.232.232 2830 typ srflx raddr 192.168.100.2 rport 58907 generation 0
↵a=ice-ufrag:TYKF98cRmZWIRAm5
↵a=ice-pwd:viHciQB6l36zfTuHdZCnJDPY
↵a=fingerprint:sha-256 10:01:2C:0C:5D:B8:CC:32:15:D3:0D:0A:D3:50:BD:13:B8:9F:87:DF:97:1C:15:13:84:80:68:83:AB:FA:44:E8
↵a=setup:actpass
↵a=mid:data
↵a=sendrecv
↵a=rtcp-mux
↵a=rtpmap:127 google-data/90000
↵a=ssrc:2123048988 cname:pRuKm8BiQ79bLvJg
↵a=ssrc:2123048988 msid:chatchannel chatchannel
↵a=ssrc:2123048988 mslabel:chatchannel
↵a=ssrc:2123048988 label:chatchannel
↵"
type
:
"offer"
__proto__
:
RTCSessionDescription
signalingState
:
"stable"
__proto__
:
RTCPeerConnection
答案 0 :(得分:1)
在我生命的最后14个小时里面出现的问题是Chrome和Firefox中的RTPDataChannels标志已经过时了。不要使用它。小心自己。现在一切都在继续。