2014-10-24 1 views
0

Существует 3 секции, серверная часть, клиент A для ПК и клиент B для Android.
Логика:
1. Когда клиент A и B подключаются к серверу, они будут уведомлены о другом ip и порту.
2. Затем A пробивает отверстие для B и сообщает серверу, что он готов для приема от B.
3. сервер сообщит B, что A готов.
4. Тогда B будет отправить сообщение A.Как заставить его работать на p2p?

Это только простой тест, тест окружающей среды являются:
1. Сервер имеет публичный IP и порт
2. Клиент А и Клиент B находятся в другой NAT

Код не работает. Два коллеги не могут общаться друг с другом. Как заставить двух равных общаться? Я буду благодарен за каждый совет.

[изменить]
Спасибо, @kha. Первый раз я публикую здесь. Я подробно расскажу о процессе.
1. Никаких исключений из этих трех разделов. У меня нет ошибок.
2. Два клиента могут подключаться к серверу и получать IP-адрес и порт другого пользователя с сервера.
3. Я отключил брандмауэр для Windows. Для android я не знаю, как это сделать.
4. Два клиента просто не могут общаться, никаких других исключений.
5. Я новичок в P2P, поэтому я хочу больше помочь в поиске проблемы.

сервера код сторона:

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.SocketException; 
import java.net.UnknownHostException; 

public class Main { 

    static EndPoint endPoint; 
    static EndPoint endPoint2; 

    /** 
    * @param args 
    * @throws IOException 
    */ 
    public static void main(String[] args) { 
     try { 
      DatagramSocket server = new DatagramSocket(5050); 
      boolean isSend = false; 
      while (true) { 
       System.out.println("start receiving..."); 

       EndPoint ep = receiveMessage(server); 

       if (endPoint == null) { 
        System.out.println("endPoint initialized"); 
        endPoint = ep; 
       } else if (endPoint2 == null) { 
        System.out.println("endPoint2 initialized"); 
        endPoint2 = ep; 
       } else { 
        if (!isSend) {//when A and B all connect to server, they will be notified another's ip and port 
         isSend = true; 
         System.out.println("send to each other"); 
         sendEndPointMessage(server, endPoint, endPoint2); 
         sendEndPointMessage(server, endPoint2, endPoint); 
        } else { 
         if ("5".equals(ep.message)) {// client A is ready 
          System.out.println("client A is ready"); 
          sendMessage(server, "6", endPoint2);// send B message that A is reay 
         } 
        } 
       } 
      } 
     } catch (SocketException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void sendEndPointMessage(DatagramSocket server, EndPoint epReceive, EndPoint epContent) { 
     try { 
      String sendStr = epContent.host + ";" + epContent.port; 
      byte[] sendBuf = sendStr.getBytes(); 
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, epReceive.addr, epReceive.port); 
      server.send(sendPacket); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

    private static void sendMessage(DatagramSocket server, String msg, EndPoint ep) { 
     try { 
      byte[] sendBuf = msg.getBytes(); 
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, ep.addr, ep.port); 
      server.send(sendPacket); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

    private static EndPoint receiveMessage(DatagramSocket server) { 
     try { 
      byte[] recvBuf = new byte[1024]; 
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length); 
      server.receive(recvPacket); 

      String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength()); 
      int port = recvPacket.getPort(); 
      InetAddress addr = recvPacket.getAddress(); 

      System.out.println("EndPoint: host:" + recvPacket.getAddress() + ", port:" + port + ", message:" + recvStr); 

      EndPoint endPoint = new EndPoint(addr, port, recvStr); 
      return endPoint; 
     } catch (IOException e) { 

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

    static class EndPoint { 
     InetAddress addr; 
     String host; 
     int port; 
     String message; 

     public EndPoint(String host, int port, String message) { 
      this.host = host; 
      this.port = port; 
      this.message = message; 

      try { 
       addr = InetAddress.getByName(host); 
      } catch (UnknownHostException e) { 
       e.printStackTrace(); 
      } 
     } 

     public EndPoint(InetAddress host, int port, String message) { 
      this.host = host.getHostAddress(); 
      this.port = port; 
      this.message = message; 

      addr = host; 
     } 
    } 

} 

Клиент A для ПК:

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.SocketException; 
import java.net.UnknownHostException; 

public class Main { 
    public static String serverAddr = "xxx.xxx.xxx.xx"; 
    public static int serverPort = 5050; 
    public static String peerIP; 
    public static int peerPort; 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 

     try { 
      final DatagramSocket client = new DatagramSocket(); 

      sendMessage(client, "1", serverAddr, serverPort); 

      while (true) { 
       System.out.println("start receiving..."); 

       String recvStr = receiveMessage(client); 

       if ("3".equals(recvStr)) { 
        sendMessage(client, "4", peerIP, peerPort); 
       } else { 
        String[] peer = recvStr.split(";"); 
        if (peer.length > 1) {// received peer ip and port 
         peerIP = peer[0]; 
         peerPort = Integer.parseInt(peer[1]); 
         sendMessage(client, "4", peerIP, peerPort);//punch a hole for client B 
         sendMessage(client, "5", serverAddr, serverPort);//tell server I am ready 
         new Thread(new Runnable() { 

          @Override 
          public void run() { 
           for (int i = 0; i < 10; i++) { 
            sendMessage(client, "4", peerIP, peerPort);//keep punch a hole for client B 
            sendMessage(client, "5", serverAddr, serverPort);//keep telling server I am ready 
            try { 
             Thread.sleep(500); 
            } catch (InterruptedException e) { 
             e.printStackTrace(); 
            } 
           } 
          } 
         }).start(); 
        } else { 
         if ("7".equals(recvStr)) {// received from client B 
          sendMessage(client, "got from android", peerIP, peerPort); 
         } 
        } 
       } 
      } 
     } catch (SocketException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static String receiveMessage(final DatagramSocket client) { 
     try { 
      byte[] recvBuf = new byte[1024]; 
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length); 
      client.receive(recvPacket); 
      String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength()); 
      String ip = recvPacket.getAddress().getHostAddress(); 
      int port = recvPacket.getPort(); 
      System.out.println("received from: host:" + ip + ", port:" + port + ", content:" + recvStr); 
      return recvStr; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private static void sendMessage(final DatagramSocket client, String sendStr, String ip, int port) { 
     try { 
      System.out.println("send out: host:" + ip + ", port: " + port + ", message:" + sendStr); 
      byte[] sendBuf; 
      sendBuf = sendStr.getBytes(); 
      InetAddress addr = InetAddress.getByName(ip); 
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, addr, port); 
      client.send(sendPacket); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
} 

Client B для Android:

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.SocketException; 
import java.net.UnknownHostException; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 

public class MainActivity extends Activity { 
    public String serverAddr = "xxx.xxx.xxx.xx"; 
    public int serverPort = 5050; 
    public String peerIP; 
    public int peerPort; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     findViewById(R.id.connectServer).setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       new Thread(new Runnable() { 

        @Override 
        public void run() { 
         connectServer(); 
        } 
       }).start(); 

      } 
     }); 
    } 

    private void connectServer() { 
     try { 
      DatagramSocket client = new DatagramSocket(); 

      sendMessage(client, "2", serverAddr, serverPort); 

      while (true) { 
       System.out.println("start receiving..."); 

       String recvStr = receiveMessage(client); 

       String[] peer = recvStr.split(";"); 
       if (peer.length > 1) {// received peer ip and port 
        peerIP = peer[0]; 
        peerPort = Integer.parseInt(peer[1]); 
       } else { 
        if ("6".equals(recvStr)) {//received from server that client A is ready      
         sendMessage(client, "7", peerIP, peerPort); // send message to client A     
        } 
       } 
      } 

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

    private String receiveMessage(DatagramSocket client) throws IOException { 
     try { 
      byte[] recvBuf = new byte[1024]; 
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length); 
      client.receive(recvPacket); 
      String ip = recvPacket.getAddress().getHostAddress(); 
      int port = recvPacket.getPort(); 
      String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength()); 
      System.out.println("received from: host:" + ip + ", port:" + port + ", content:" + recvStr); 
      return recvStr; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private void sendMessage(DatagramSocket client, String sendStr, String ip, int port) { 
     try { 
      System.out.println("send out: host:" + ip + ", port:" + port + ", mesasge:" + sendStr); 
      byte[] sendBuf; 
      sendBuf = sendStr.getBytes(); 
      InetAddress addr = InetAddress.getByName(ip); 
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, addr, port); 
      client.send(sendPacket); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
} 
+1

Объясните, что вы подразумеваете под «нерабочим». – kingdamian42

+0

@ kingdamian42 изменен, не работает означает, что два сверстника не могут общаться друг с другом. –

+0

Какая часть не работает? Какие ошибки вы получаете? Могут ли они подключиться к вашему серверу и получить IP-адреса друг друга? Есть ли проблемы с брандмауэром? Вы получаете сетевые исключения? Вы пытались сузить проблему и изолировать причину? – kha

ответ

0

я получил еще один сервер для тестирования. И найдите, что от клиента B с тем же портом к серверу A и серверу B существует два разных порта, открытых NAT.
Мой NAT - это симметричный NAPT. Поэтому я думаю, что это основная причина, по которой не могут общаться два сверстника.
@ KunjanThadani, вы правы.

+0

Хорошо. Вы можете попробовать прогнозирование портов. Но это все равно будет сложной процедурой и не обязательно работать. –

+0

@ KunjanThadani, по моему тесту, открытые порты не были в обычном порядке. Поэтому я думаю, что единственный способ - передать сообщение через сервер. –

+0

Хорошо. Да, ретрансляция через сервер будет работать. Но я предлагаю вам использовать tcp вместо этого, если речь идет только о «текстовых сообщениях». Это будет более надежным. –