【问题标题】:WebRTC Android multi-user text chat using DataChannels使用 DataChannels 的 WebRTC Android 多用户文本聊天
【发布时间】:2020-06-23 06:29:21
【问题描述】:

我正在为多用户的 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));
        }
    }

【问题讨论】:

    标签: webrtc webrtc-android


    【解决方案1】:

    数据通道不是用来聊天的,即使是一对一聊天也不行。想象一个场景,当AB 发送消息,而B 不在线接收它。 A 可以等待 B 再次在线,但如果 A 不在线而 B 再次在线怎么办。现在将此场景扩展到多用户,它只是不能提供正确的体验。

    对于具有存储和转发功能的多方聊天,您需要更可靠的东西 - 看看这里https://mesibo.com/livedemo/ 它具有多用户视频/语音会议、1 对 1 和群聊。源代码在这里https://github.com/mesibo/conferencing。尽管此演示使用 mesibo API,但您可以使用您选择的任何 API。

    【讨论】:

    • 我不只是使用 dataChannel 进行聊天,我也会使用它进行文件传输,我只是尝试将它用于聊天,看看 dataChannels 如何用于多个对等点,如果这个问题比上述两个功能都解决了,你能帮我解决这个问题吗?
    【解决方案2】:

    我可以建议的两件事:

    1. dChannel 将仅保存您在对等方上打开的最后一个数据通道。考虑将其设为数组并保存所有数据通道。
    2. 向 SDPConstraints DtlsSrtpKeyAgreement = true 和 internalSctpDataChannels = true 添加可选约束

    【讨论】:

    • 实际上,我将 dChannel 存储在 dataChannels 列表中。我也尝试添加两个可选约束,问题仍然存在。此外,每当我在 PeerConnection.Observer 中实现 onRenegotiationNeeded 方法时(我将接口实现为一个类,并在主要活动中创建这些对象时使用覆盖来实现方法的附加功能),它会被多次调用并使应用程序崩溃
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 2015-01-25
    • 2012-01-14
    相关资源
    最近更新 更多