java – Android上的UDP打孔; UDP服务器

前端之家收集整理的这篇文章主要介绍了java – Android上的UDP打孔; UDP服务器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我正在尝试在Android上为我的udp服务器实现udp打孔.事情应该像这样:

>客户端(在nat之后;可能是3G,……)向服务器发送DatagramPacket(服务器具有公共IP;端口也称为45555).客户端重复发送具有给定延迟的数据报
>一旦服务器收到数据报,它就会每隔500毫秒发回一次数据报(“信号”).
>如果打孔工作,客户应该接收这些信号

这是我当前的客户端实现(Android):

  1. //in onCreate()
  2. DatagramSocket socket = new DatagramSocket(46222);
  3. socket.setSoTimeout(2000);
  4. final Thread t = new Thread(new Runnable(){
  5. @Override
  6. public void run() {
  7. int delay = Integer.parseInt(e2.getText().toString());//e1 and e2 are EditTexts
  8. String ip = e1.getText().toString();
  9. try {
  10. DatagramPacket packet = new DatagramPacket(new byte[1],1,InetAddress.getByName(ip),45555);
  11. while(!cleanUp){//cleanUp is set to true in onPause()
  12. lock.lock(); //Lock lock = new ReentrantLock();
  13. socket.send(packet);
  14. lock.unlock();
  15. Thread.sleep(delay);
  16. }
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }finally{
  20. if(socket!=null)
  21. socket.close();
  22. }
  23. }
  24. });
  25. final Thread t2 = new Thread(new Runnable(){
  26. @Override
  27. public void run() {
  28. try {
  29. Thread.sleep(1000);
  30. DatagramPacket packet = new DatagramPacket(new byte[1],1);
  31. while(!cleanUp){
  32. lock.lock();
  33. try{
  34. socket.receive(packet);
  35. }catch(SocketTimeoutException e){
  36. lock.unlock();
  37. Thread.sleep(15);
  38. continue;
  39. }
  40. lock.unlock();
  41. final String s = tv.getText().toString()+"signal\n";
  42. MainActivity.this.runOnUiThread(new Runnable(){
  43. @Override
  44. public void run() {
  45. tv.setText(s);//tv is a TextView
  46. }
  47. });
  48. Thread.sleep(10);
  49. }
  50. } catch (Exception e) {
  51. e.printStackTrace();
  52. }
  53. finally{
  54. if(socket!=null)
  55. socket.close();
  56. }
  57. }
  58. });
  59. //start both threads

这是服务器端实现(Java):

  1. //int static void main(String[] args):
  2. final Thread t = new Thread(new Runnable(){
  3. @Override
  4. public void run() {
  5. try {
  6. DatagramPacket packet = new DatagramPacket(new byte[1],addr,port);
  7. DatagramSocket socket = new DatagramSocket();
  8. System.out.println("send");
  9. while(true){
  10. socket.send(packet);
  11. Thread.sleep(500);
  12. }
  13. } catch (Exception e) {
  14. // TODO Auto-generated catch block
  15. e.printStackTrace();
  16. }
  17. }
  18. });
  19. final Thread t2 = new Thread(new Runnable(){
  20. @Override
  21. public void run() {
  22. try {
  23. DatagramPacket packet = new DatagramPacket(new byte[1],1);
  24. DatagramSocket socket = new DatagramSocket(45555);
  25. socket.receive(packet);
  26. addr = packet.getAddress(); //private static field InetAddress addr
  27. port = packet.getPort();
  28. System.out.println(addr+":"+ packet.getPort()); //field int port
  29. t.start();
  30. while(true){
  31. socket.receive(packet);
  32. System.out.println("idle");
  33. }
  34. } catch (Exception e) {
  35. // TODO Auto-generated catch block
  36. e.printStackTrace();
  37. }
  38. }
  39. });
  40. t2.start();

当客户端和服务器位于同一个专用网络中时,一切正常.为了模仿公共服务器,我在我的计算机上运行服务器端代码,并在我的路由器上设置一个端口(具有公共IP)*.客户端将其数据包发送到路由器的公共IP.但在这两种情况下(我的智能手机通过我的wlan网络/ 3G或E连接到互联网)没有收到信号(服务器接收客户端的数据报)

那么为什么打孔过程不起作用呢?

问候

*:路由器会将发送到其端口45555的任何udp数据包转发到我的计算机

最佳答案
不同的套接字绑定到不同的专用端口,并使用NAT的不同公共端口.您正在通过不同的套接字接收和发送.使用您收到数据的同一套接字发送.否则您的发送套接字使用路由器的不同公共端口将数据发送到您的客户端NAT.您的客户端NAT丢弃的此数据包,因为它来自相同的IP但未知端口.

猜你在找的Android相关文章