3

有谁知道如何做 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");
4

1 回答 1

0

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

 agent.addCandidateHarvester(
   new StunCandidateHarvester(
       new TransportAddress(
           InetAddress.getByName('stun.l.google.com'),
           19302,
           Transport.UDP)));
于 2015-10-23T04:19:42.197 回答