【问题标题】:P2P message sending using NAT punch-through in Android在 Android 中使用 NAT 穿透发送 P2P 消息
【发布时间】:2014-06-27 22:24:01
【问题描述】:

我尝试使用Kryonet(使用套接字通信)将消息从一部手机发送到另一部手机,并且我打算通过存储客户端的公共地址来使用 NAT 穿透。

使用如下代码:

public class MainActivity extends Activity implements View.OnClickListener
{
  /**
   * Called when the activity is first created.
   */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button button = ((Button) findViewById(R.id.btnTest));
    button.setOnClickListener(this);
    TextView textViewOwn = ((TextView) findViewById(R.id.lblOwnIP));
    textViewOwn.setText(getLocalIpAddress()+"\n"+GetGateway());
    try
    {
      Server server = new Server();
      server.start();
      server.bind(54555, 54777);
      Log.i("DEBUG", "Server is listening");
      final TextView textView = ((TextView) findViewById(R.id.txtMessage));
      server.addListener(new Listener()
      {
        public void received(Connection connection, Object object)
        {
          if (object instanceof String)
          {
            String request = (String) object;
            Log.i("DEBUG", request);
            ShowMessage(request, textView);
            String response = "Thanks";
            connection.sendTCP(response);
          }
        }
      });

    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public static String getLocalIpAddress() {
    try {
      for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
        NetworkInterface intf = en.nextElement();
        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
          InetAddress inetAddress = enumIpAddr.nextElement();
          if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
            return inetAddress.getHostAddress();
          }
        }
      }
    } catch (SocketException ex) {
      ex.printStackTrace();
    }
    return null;
  }

  private String GetGateway()
  {
    DhcpInfo d;
    WifiManager wifii;
    wifii= (WifiManager) getSystemService(Context.WIFI_SERVICE);
    d=wifii.getDhcpInfo();
    int gatewayip = d.gateway;
    String mask = Formatter.formatIpAddress(gatewayip);
    return mask;
  }

  private void ShowMessage(final String request, final TextView textView)
  {
    runOnUiThread(new Runnable()
    {
      @Override
      public void run()
      {
        textView.setText(request);
      }
    });
  }

  @Override
  public void onClick(View view)
  {
    final String ip = ((EditText) findViewById(R.id.txtIP)).getText().toString();
    if (TextUtils.isEmpty(ip))
    {
      Toast.makeText(this, "No IP address", Toast.LENGTH_SHORT).show();
      return;
    }
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        try
        {
          Client client = new Client();
          client.start();

          client.connect(5000, ip, 54555, 54777);
          Log.i("DEBUG", "Client is sending: "+ip);
          runOnUiThread(new Runnable()
          {
            @Override
            public void run()
            {
              Toast.makeText(MainActivity.this, "Client is sending: "+ip, Toast.LENGTH_SHORT).show();
            }
          });

          String request = "Here is the request";
          client.sendTCP(request);
        }
        catch (final Exception e)
        {
          e.printStackTrace();
          runOnUiThread(new Runnable()
          {
            @Override
            public void run()
            {
              Toast.makeText(MainActivity.this, "Client has errors: "+e.toString(), Toast.LENGTH_SHORT).show();

            }
          });
        }
      }
    };
       Thread thread=new Thread(runnable);
    thread.start();
  }
}

如果手机在同一个 WIFI 上,它可以正常工作。如果其中一个在 3G 上,我会得到一个外部 IP 地址(例如:100.65.96..),以及一个本地地址作为网关。由于知道外部 IP 是 NAT PT 的关键,我认为收到消息就足够了,但我得到了 超时

我还应该实现什么让 3G 手机收到消息?

【问题讨论】:

    标签: android p2p nat kryonet


    【解决方案1】:

    您可以使用有助于在手机之间建立连接的中介服务器来实现。

    1. 创建一个可以接受 UDP 套接字并可以存储连接到它的手机的公共地址的服务器程序
    2. 使用电话 A 连接到该服务器以注册其公共地址
    3. 使用电话B连接服务器,询问电话A的公共地址
    4. 获得该地址后,您可以使用其公共地址创建从 电话 A电话 B直接套接字。 NAT 将完成剩下的工作,路由器会将包发送到手机的私有地址

    【讨论】:

    • 如果你想使用 TCP 而不是 UDP 怎么办?如果那不可能……我想我必须免费实现 TCP 为您提供的所有东西,但在 UDP 中……
    • 我认为运营商会阻止 A 之前没有直接联系过的任何直接传入 A 的连接
    猜你喜欢
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    相关资源
    最近更新 更多