P2P消息使用NAT穿通在Android中发送 [英] P2P message sending using NAT punch-through in Android

查看:765
本文介绍了P2P消息使用NAT穿通在Android中发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着从一个手机发送消息到另一个使用 Kryonet (使用socket通讯)和我打算用NAT穿通通过存储用户的公网地址。

I try to send a message from one phone to another using Kryonet (that uses socket communication) and I intend to use NAT punch-through by storing the public address of the clients.

以下code时:

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的关键,我认为这是足以获得消息,但我得到一个的超时

If the phones are on the same WIFI, it works okay. If one of them is on 3G, I get an external IP address (like: 100.65.96..), and a local address as gateway. As knowing the external IP is the key for NAT PT, I thought it is enough to get the message, but I get a timeout.

还有什么我应该实现,使3G手机得到的消息?

What else should I implement to make the 3G phone get the message?

推荐答案

您可以通过使用中介服务器,有助于建立手机之间的连接,做到这一点。

You can do it by using a mediator server that helps establishing the connection between the phones.


  1. 创建一个服务器程序,可以接受UDP套接字,并可以存储连接到它
  2. 手机的公开地址
  3. 连接到该服务器使用的手机A 的注册公共地址

  4. 使用的话机B 的连接到服务器要求的公网地址的手机A

  5. 一旦你的地址,你可以通过使用其公共地址来创建的话机B 的一个直接套接字来自的手机A 的。该NAT将做休息,和路由器将包发送到手机上的私人地址

  1. Create a server program that can accept UDP sockets and can store the public address of the phone that connects to it
  2. Connect to that server with phone A to register its public address
  3. Use phone B to connect to the server for asking the public address of phone A
  4. Once you have that address, you can create a direct socket from phone A to phone B by using its public address. The NAT will do the rest, and the router will send the packages to the phone's private address

这篇关于P2P消息使用NAT穿通在Android中发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆