Соединение PeerJS/WebRTC не выполняется при передаче быстрых фрагментов
Я использую PeerJS
, но думал, что эта проблема может быть примерно WebRTC
в общем, надеюсь, что вы можете мне помочь:
Я пытаюсь написать простой обмен файлами одноранговой сети. Я использую serialisation: "none"
для PeerJS
соединения DataChannel
, так как я отправляю только чистый ArrayBuffers
.
Все хорошо с файлами около 10 Мб, но у меня проблемы с отправкой большего файла (30+ мб), например, после отправки aroung 10-20 первых фрагментов соединения с файлом в размере 900 мб между пэрами начинают метать Connection is not open. You should listen for the "open" event before sending messages
. (со стороны Sender
)
Моя настройка:
Файл, перетаскиваемый, чтобы перетащить & drop, Sender
использует FileReader
, чтобы читать его как ArrayBuffer
в кусках размером 64x1024 байта (без разницы с 16x1024), и как только каждый кусок читается - он отправляется через peer.send(ChunkArrayBuffer).
Reciever
создает blob
из каждого полученного фрагмента, после того как завершена передача, вы получите полный blob
из них и даст ссылку пользователю.
Мои настройки подключения сверстников:
var con = peer.connect(peerid, {
label: "file",
reliable: true,
serialization: "none"
})
Моя функция отправки:
function sliceandsend(file, sendfunction) {
var fileSize = file.size;
var name = file.name;
var mime = file.type;
var chunkSize = 64 * 1024; // bytes
var offset = 0;
function readchunk() {
var r = new FileReader();
var blob = file.slice(offset, chunkSize + offset);
r.onload = function(evt) {
if (!evt.target.error) {
offset += chunkSize;
console.log("sending: " + (offset / fileSize) * 100 + "%");
if (offset >= fileSize) {
con.send(evt.target.result); ///final chunk
console.log("Done reading file " + name + " " + mime);
return;
}
else {
con.send(evt.target.result);
}
} else {
console.log("Read error: " + evt.target.error);
return;
}
readchunk();
};
r.readAsArrayBuffer(blob);
}
readchunk();
}
Любые идеи, что может вызвать это?
Обновление: установка 50 мс. Тайм-аут между передачами каналов помог немного, загрузка файла 900mb достигла 6% (вместо 1 - 2% ранее), прежде чем начинать бросать ошибки. Может быть, это какой-то предел одновременных операций через DataChannel
или переполнение какого-то буфера DataChannel
?
Update1: Здесь мой объект соединения PeerJS
с объектом DataChannel
внутри него:
![Object visualization in Google Chrome]()
Ответы
Ответ 1
Хорошие новости все!
Это было переполнение буфера проблемы DataChannel
, спасибо к этой статье http://viblast.com/blog/2015/2/25/webrtc-bufferedamount/
bufferedAmount
является свойством объекта DataChannel
(DC
), который в последней версии Chrome
отображает количество данных в байтах, находящихся в настоящее время в буфере, когда оно превышает 16 МБ - постоянный ток закрыт.
Поэтому любой, кто столкнется с этой проблемой, должен реализовать механизм буферизации на уровне приложения, который будет следить за этим свойством и при необходимости сдерживать сообщения. Также имейте в виду, что в версиях Chrome
до 37
одно и то же свойство отображает количество (не размер) сообщений, и больше того, что оно сломано под окнами и отображает 0, но с v < 37 при переполнении DC
не закрыто - исключено только исключение, которое также можно поймать для указания буфера переполнение.
Я сделал редактирование в peer.js
неминифицированном коде для себя, здесь вы можете увидеть оба метода в одной функции (для большей части исходного кода вы можете посмотреть https://github.com/peers/peerjs/blob/master/dist/peer.js#L217)
DataConnection.prototype._trySend = function(msg) {
var self = this;
function buffering() {
self._buffering = true;
setTimeout(function() {
// Try again.
self._buffering = false;
self._tryBuffer();
}, 100);
return false;
}
if (self._dc.bufferedAmount > 15728640) {
return buffering(); ///custom buffering if > 15MB is buffered in DC
} else {
try {
this._dc.send(msg);
} catch (e) {
return buffering(); ///custom buffering if DC exception caught
}
return true;
}
}
Также была открыта проблема на PeerJS
GitHub: https://github.com/peers/peerjs/issues/291