webrtc - 使用 DataChannels 的 WebRTC Android 多用户文本聊天
问题描述
我正在为多用户使用 webRTC 应用程序的网格架构,视频聊天适用于多用户,对于文本聊天,我在创建报价的对等方上创建了一个 dataChannel,而 onDataChannel 处理程序在另一个对等方上创建了一个 dataChannel。文本聊天适用于 2 个用户,但是当有 3 个用户时,第一个客户端(加入)能够看到所有其他客户端消息,但只能向第二个客户端(加入)发送消息,第二个客户端(加入)是能够看到来自第一个客户端的消息并仅发送给第一个客户端,第三个客户端没有收到消息但可以发送给第一个客户端。
PeerConnection.Observer 中的 onDataChannel 事件处理程序
@Override
public void onDataChannel(DataChannel dataChannel) {
Log.d("DataChannel", "onDataChannel" + " , state: " + dataChannel.state());
DataChannel.Observer dcObserver = new DcObserver(){
@Override
public void onStateChange() {
Log.d(TAG, "onStateChange: remote data channel state: " + dChannel.state().toString());
}
@Override
public void onMessage(DataChannel.Buffer buffer) {
Log.d(TAG, "onMessage: got message");
readMessage(buffer.data);
}
};
dataChannel.registerObserver(dcObserver);
dataChannels.add(dataChannel);
dcObservers.add(dcObserver);
}
});
在创建 peerConnections 时创建 DataChannel
@Override
public void onNewPeerJoined(String socketId, boolean createOffer) {
showToast("Remote Peer Joined");
PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
if (createOffer) {
dChannel = peerConnection.createDataChannel("DataChannel",new DataChannel.Init());
DataChannel.Observer dcObserver = new DcObserver(){
@Override
public void onStateChange() {
Log.d(TAG, "onStateChange: remote data channel state: " + dChannel.state().toString());
}
@Override
public void onMessage(DataChannel.Buffer buffer) {
Log.d(TAG, "onMessage: got message");
readMessage(buffer.data);
}
};
dChannel.registerObserver(dcObserver);
dcObservers.add(dcObserver);
dataChannels.add(dChannel);
sdpConstraints = new MediaConstraints();
sdpConstraints.mandatory.add(
new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
sdpConstraints.mandatory.add(
new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
//sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
peerConnection.createOffer(new CustomSdpObserver("localCreateOffer") {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
super.onCreateSuccess(sessionDescription);
peerConnection.setLocalDescription(new CustomSdpObserver("localSetLocalDesc"), sessionDescription);
Log.d("onCreateSuccess", "SignallingClient emit ");
SignallingClient.getInstance(roomName).emitSessionDescription(sessionDescription, socketId);
}
}, sdpConstraints);
}
}
发送消息
public void sendMessage() {
String message = editText.getText().toString();
if (message.isEmpty()) {
return;
}
editText.setText("");
textView.append(HtmlCompat.fromHtml("<b>" + userName + "</b>",HtmlCompat.FROM_HTML_MODE_LEGACY));
textView.append(": " + message + "\n");
String str = "<b>" + userName + "</b> : " + message;
ByteBuffer data = stringToByteBuffer("-s" + str, Charset.defaultCharset());
for (int i = 0; i < dataChannels.size(); i++){
Log.d("info","send_data dataChannel" + i);
dataChannels.get(i).send(new DataChannel.Buffer(data, false));
}
}
解决方案
我可以建议的两件事:
- dChannel 将仅保存您在对等方上打开的最后一个数据通道。考虑使其成为一个数组并保存所有数据通道。
- 将可选约束添加到 SDPConstraints DtlsSrtpKeyAgreement = true 和 internalSctpDataChannels = true
推荐阅读
- xpath - XQuery 每天获取最高值
- virtual-reality - 我对虚拟现实很好奇。如何找到有关虚拟现实的课程?
- javascript - 如何在对象数组中设置每个对象的属性?
- python - 有条件地删除熊猫中相同的列对
- angular - Ionic 4 使用 setInterval 函数试图每秒调用一个函数,但该函数从未调用
- linux - 在 grep 匹配的模式输出行前面打印文件名
- python - 按钮在 pycharm 中使用 python 和 tkinter 在新窗口中打开主页的重复窗口
- javascript - 对于 click() 方法,for 循环不能正常工作
- awk - 在图案后提取线条
- javascript - 填充同一文档中的 FORM 字段的可点击链接(但具有多个 FORM)