【问题标题】:Ice4J: Ice State Failed on 4G networkIce4J:4G 网络上的 Ice State 失败
【发布时间】:2014-09-11 22:42:54
【问题描述】:

有人知道如何做 Ice4j 的 TURN 部分吗?我已经设法对其进行了编码,以便它在手机连接 WiFi 时工作,但在移动网络上时不能工作。

我通过 TCP 发送代理信息,然后手动建立连接,而不是使用信令过程。 TCP 连接已经工作正常,所以我认为不是 TCP 问题。也许我构建代理错误?

我知道如果 STUN 不起作用,您应该使用 TURN 服务器,我提供了大量公共 TURN 服务器,但我可能遗漏了一些东西。也许数据包没有正确发送?

错误:(大多数情况下无法发送 ALLOCATE-REQUEST(0X3))

Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent createMediaStream
INFO: Create media stream for data
Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent createComponent
INFO: Create component data.1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent gatherCandidates
INFO: Gather candidates for component data.1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.harvest.HostCandidateHarvester harvest
INFO: End candidate harvest within 160 ms, for org.ice4j.ice.harvest.HostCandidateHarvester, component: 1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.harvest.StunCandidateHarvest sendRequest
INFO: Failed to send ALLOCATE-REQUEST(0x3)[attrib.count=3 len=32 tranID=0x9909DC6648016A67FDD4B2D8] through /192.168.0.8:5001/udp to stun2.l.google.com:19302:5001/udp
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /fe80:0:0:0:c8ce:5a17:c339:cc40%4:5001/udp -> /fe80:0:0:0:14e8:f3ff:fef3:6a21:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /fe80:0:0:0:380d:2a4c:b350:eea8%8:5001/udp -> /fe80:0:0:0:14e8:f3ff:fef3:6a21:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /192.168.0.8:5001/udp -> /100.64.74.58:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /192.168.0.8:5001/udp -> /100.64.74.58:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient updateCheckListAndTimerStates
INFO: CheckList will failed in a few seconds if nosucceeded checks come
Sep 11, 2014 3:36:17 PM org.ice4j.ice.ConnectivityCheckClient$1 run
INFO: CheckList for stream data FAILED
Sep 11, 2014 3:36:17 PM org.ice4j.ice.Agent checkListStatesUpdated
INFO: ICE state is FAILED

脚本(服务器端和客户端都有类似的代码):

Agent agent = new Agent();
        agent.setControlling(false);

        StunCandidateHarvester stunHarv = new StunCandidateHarvester(new TransportAddress("sip-communicator.net", port, Transport.UDP));
        StunCandidateHarvester stun6Harv = new StunCandidateHarvester(new TransportAddress("ipv6.sip-communicator.net", port, Transport.UDP));

        agent.addCandidateHarvester(stunHarv);
        agent.addCandidateHarvester(stun6Harv);
        String[] hostnames = new String[] { "130.79.90.150",
                "2001:660:4701:1001:230:5ff:fe1a:805f",
                "jitsi.org",
                "numb.viagenie.ca",
                "stun01.sipphone.com",
                "stun.ekiga.net",
                "stun.fwdnet.net",
                "stun.ideasip.com",
                "stun.iptel.org",
                "stun.rixtelecom.se",
                "stun.schlund.de",
                "stun.l.google.com:19302",
                "stun1.l.google.com:19302",
                "stun2.l.google.com:19302",
                "stun3.l.google.com:19302",
                "stun4.l.google.com:19302",
                "stunserver.org",
                "stun.softjoys.com",
                "stun.voiparound.com",
                "stun.voipbuster.com",
                "stun.voipstunt.com",
                "stun.voxgratia.org",
                "stun.xten.com",};

        LongTermCredential longTermCredential = new LongTermCredential("guest", "anon");

        for (String hostname : hostnames)
            agent.addCandidateHarvester(new TurnCandidateHarvester(new TransportAddress(hostname, port, Transport.UDP), longTermCredential));

        //Build a stream for agent
        IceMediaStream stream = agent.createMediaStream("data");
        try {
            Component c = agent.createComponent(stream, Transport.UDP, port, port, port+100  );
            String response = "";
            List<LocalCandidate> remoteCandidates = c.getLocalCandidates();
            for(Candidate<?> can : remoteCandidates) {
                response += "||" + can.toString();
            }
            response = "Video||" + agent.getLocalUfrag() + "||" + agent.getLocalPassword() + "||" + c.getDefaultCandidate().toString() + response;
            System.out.println("Server >>> " + response);
            DataOutputStream outStream = new DataOutputStream(client.getOutputStream());
            outStream.write(response.getBytes("UTF-8"));
            outStream.flush();

            List<IceMediaStream> streams = agent.getStreams();
            for(IceMediaStream localStream : streams) {
                List<Component> localComponents = localStream.getComponents();
                for(Component localComponent : localComponents) {
                    for(int i = 3; i < info.length; i++) {
                        String[] detail = info[i].split(" ");   //0: Foundation
                                                                //1: Component ID
                                                                //2: Transport
                                                                //3: Priority #
                                                                //4: Address (Needed with Port # to create Transport Address)
                                                                //5: Port # (Needed with Address to create Transport Address)
                                                                //6: -filler: "Type" is next field-
                                                                //7: Candidate Type

                        String[] foundation = detail[0].split(":"); //Turn "Candidate:#" -> "Candidate" and "#". We use "#"

                        localComponent.addRemoteCandidate(new RemoteCandidate(new TransportAddress(detail[4], Integer.valueOf(detail[5]), Transport.UDP), c, CandidateType.HOST_CANDIDATE, foundation[1], Long.valueOf(detail[3]), null));
                    }
                    String[] defaultDetail = info[3].split(" ");
                    String[] defaultFoundation = defaultDetail[0].split(":");
                    localComponent.setDefaultRemoteCandidate(new RemoteCandidate(new TransportAddress(defaultDetail[4], Integer.valueOf(defaultDetail[5]), Transport.UDP), c, CandidateType.HOST_CANDIDATE, defaultFoundation[1], Long.valueOf(defaultDetail[3]), null));
                }
                localStream.setRemoteUfrag(info[1]);
                localStream.setRemotePassword(info[2]);
            }
            agent.startConnectivityEstablishment();
            System.out.println("ICEServer <><><> Completed");

【问题讨论】:

  • 我开始认为 4G 不允许向任一方向发送 UDP 数据包,这会导致失败...
  • 不确定输出如何与代码匹配,因为代码显示使用 TurnCandidateHarvester 而不是 StunCandidateHarvester 用于看起来像 Stun 服务器的东西。看起来 google stun 服务器是端口 19302,而不是 url 的一部分,不太确定....
  • 我尝试了 UDP 看看它是否可以工作,但我认为我也遇到了问题,但我还没有深入研究它。您应该知道 Ice4J 也有 TCP 方法。我自己很好奇。如果您有兴趣,请告诉我。
  • 进程的 TCP 部分工作,并且在该路径上建立了连接,但 UDP 没有。如果任一测试失败,我不确定 Ice4J 测试是否失败,但我认为这就是发生的事情。你有什么建议?
  • 通常 ICE 使用 UDP。有时它们会被阻止,因此您可以使用 TCP 传输蜂窝网络肯定允许通过的视频/音频。我注意到 TCP 协议似乎没有完成并抛出错误....您使用的是 TURN 服务器吗?当我认为你想要 STUN 时,你的代码正在调用 TURN 服务器......

标签: java android sockets stun ice4j


【解决方案1】:

我现在意识到,您的 TURN 服务器列表似乎大部分实际上是 STUN 服务器(不确定前两个)。如果有的话,它们应该被添加为 STUN 服务器:

 agent.addCandidateHarvester(
   new StunCandidateHarvester(
       new TransportAddress(
           InetAddress.getByName('stun.l.google.com'),
           19302,
           Transport.UDP)));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多