如何使用 Stun 和 ice4j 接收公共 IP 和端口
Posted
技术标签:
【中文标题】如何使用 Stun 和 ice4j 接收公共 IP 和端口【英文标题】:How to receive public IP and Port using Stun and ice4j 【发布时间】:2016-08-18 03:56:54 【问题描述】:我会尽量简短。
我希望在不通过服务器的情况下创建 2 个 java 应用程序(稍后将被传输到 android)之间的通信。因此,我花了数周时间环顾四周,经过大量工作,我发现了 stun 和 ice4j。我找到了here 对如何使用 ice4j 的最佳解释,它几乎向我展示了如何将 stun 服务器添加到代理(我真的不知道代理是什么,只是它管理我的通信使用 STUN 和 TURN),通过以下代码:
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ice4j.Transport;
import org.ice4j.TransportAddress;
import org.ice4j.ice.Agent;
import org.ice4j.ice.IceMediaStream;
import org.ice4j.ice.harvest.StunCandidateHarvester;
public class ice4jTesting
public static void main(String[] args)
Agent agent = new Agent();
String[] hostnames = new String[] "jitsi.org", "numb.viagenie.ca", "stun.ekiga.net";
for(String hostname: hostnames)
try
TransportAddress address;
address = new TransportAddress(InetAddress.getByName(hostname), 3478, Transport.UDP);
agent.addCandidateHarvester(new StunCandidateHarvester(address));
catch (UnknownHostException ex)
Logger.getLogger(SimpleStun.class.getName()).log(Level.SEVERE, null, ex);
IceMediaStream stream = agent.createMediaStream("audio");
int port = 5000;
try
agent.createComponent(stream, Transport.UDP, port, port, port+100);
// The three last arguments are: preferredPort, minPort, maxPort
catch (IllegalArgumentException | IOException ex)
Logger.getLogger(SimpleStun.class.getName()).log(Level.SEVERE, null, ex);
然而,在此之后,本教程使用SDPUtils
(我在github 上找到的ice4j 源代码中的一个类)从代理接收SDP 信息。但是我从the central maven repository 获得了ice4j.jar,并将其添加到我的netbeans 常规项目中(我这样做是因为我对maven 不是很熟悉,只是想在我的常规项目中添加一个常规库)。这个 jar 库没有 SDPUtils
类,而且由于我对这段代码的理解不够,无法自己修复它,我想知道你们中的任何人是否可以帮助我修复上面的代码,或者给我看一个例子关于如何回答标题上的问题。
但是,除非您可以按照我在上一句中所说的进行操作,或者向我指出一些示例代码,否则您的帮助很可能不会有用,因为我在精神上无法完全理解这背后的理论,因为很多我不知道的概念。
我必须在本周末之前解决这个问题,如果我不这样做,我会很糟糕。因此,如果您可以或知道有人可以提供帮助,我将不胜感激。
感谢您到目前为止阅读并尝试提供帮助:)
【问题讨论】:
【参考方案1】:你去吧SdpUtils.java
实际上,我也在从事与我的大学项目相同的工作。从上周开始,我正在挖掘网络以通过 nat 建立 p2p 连接。 我知道您在代码片段上方获得的表格,我想通知您该代码中有错误这是我更正的那个
import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import org.ice4j.Transport;
import org.ice4j.TransportAddress;
import org.ice4j.ice.Agent;
import org.ice4j.ice.IceMediaStream;
import org.ice4j.ice.harvest.StunCandidateHarvester;
public class IceTest
public static void main(String[] args) throws Exception
Agent agent = new Agent(); // A simple ICE Agent
/*** Setup the STUN servers: ***/
String[] hostnames = new String[] "jitsi.org", "numb.viagenie.ca", "stun.ekiga.net" ;
// Look online for actively working public STUN Servers. You can find
// free servers.
// Now add these URLS as Stun Servers with standard 3478 port for STUN
// servrs.
for (String hostname : hostnames)
try
// InetAddress qualifies a url to an IP Address, if you have an
// error here, make sure the url is reachable and correct
TransportAddress ta = new TransportAddress(InetAddress.getByName(hostname), 3478, Transport.UDP);
// Currently Ice4J only supports UDP and will throw an Error
// otherwise
agent.addCandidateHarvester(new StunCandidateHarvester(ta));
catch (Exception e)
e.printStackTrace();
/*
* Now you have your Agent setup. The agent will now be able to know its
* IP Address and Port once you attempt to connect. You do need to setup
* Streams on the Agent to open a flow of information on a specific
* port.
*/
IceMediaStream stream = agent.createMediaStream("audio");
int port = 5000; // Choose any port
try
agent.createComponent(stream, Transport.UDP, port, port, port + 100);
// The three last arguments are: preferredPort, minPort, maxPort
catch (BindException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IllegalArgumentException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
/*
* Now we have our port and we have our stream to allow for information
* to flow. The issue is that once we have all the information we need
* each computer to get the remote computer's information. Of course how
* do you get that information if you can't connect? There might be a
* few ways, but the easiest with just ICE4J is to POST the information
* to your public sever and retrieve the information. I even use a
* simple php server I wrote to store and spit out information.
*/
String toSend = null;
try
toSend = SdpUtils.createSDPDescription(agent);
// Each computersends this information
// This information describes all the possible IP addresses and
// ports
catch (Throwable e)
e.printStackTrace();
/*The String "toSend" should be sent to a server. You need to write a PHP, Java or any server.
* It should be able to have this String posted to a database.
* Each program checks to see if another program is requesting a call.
* If it is, they can both post this "toSend" information and then read eachother's "toSend" SDP string.
* After you get this information about the remote computer do the following for ice4j to build the connection:*/
String remoteReceived = ""; // This information was grabbed from the server, and shouldn't be empty.
SdpUtils.parseSDP(agent, remoteReceived); // This will add the remote information to the agent.
//Hopefully now your Agent is totally setup. Now we need to start the connections:
agent.addStateChangeListener(new StateListener()); // We will define this class soon
// You need to listen for state change so that once connected you can then use the socket.
agent.startConnectivityEstablishment(); // This will do all the work for you to connect
此代码需要设置 SIP 服务器,并且在 ice4j 测试中的那个说的是别的,看看Ice.java
【讨论】:
我什至不记得这个帖子还在这里。感谢您的回答!我很快就会对此进行调查,我一定会向您发送一封电子邮件。 看看UDP Hole Punching以上是关于如何使用 Stun 和 ice4j 接收公共 IP 和端口的主要内容,如果未能解决你的问题,请参考以下文章
需要帮助设置用于 p2p 数据传输的 udp 打孔。无法让 STUN 工作
如何从 STUN 请求中获取我的外部 IP 地址和外部端口号?