2015-11-15 2 views
1

Я написал базовый клиентский сервер udp, где один android отправляет сообщение серверу, а сервер передает его остальным клиентам.Android может отправить udp, но не получать

Проблема заключается в том, что входящие сообщения udp попадают на сервер, а сервер передает их обратно, но они никогда не доходят до остальных устройств.

Что действительно удивительно в том, что если я использую сервер в качестве сервера эхо-сигналов (например, для передачи только отправителю), тогда все работает. Все гнезда клиента и сервера использовать тот же порт 2706

Серверный код

while (true) { 
    DatagramPacket packetToReceive = new DatagramPacket(new byte[2048], 2048); 
    try { 
     listenerSocket.receive(packetToReceive); 
     InetAddress senderAddress = packetToReceive.getAddress(); 
     relayedBytes += packetToReceive.getLength(); 

     if (!connectedClients.contains(senderAddress)) { 
      connectedClients.add(senderAddress); 
     } 

     for (InetAddress addr : connectedClients) { 
      // commenting this line will make it an echo server 
      if (!addr.equals(senderAddress)) 
      { 
       //The following actually prints the ips of the android 
       //devices so it knows where to send 

       System.out.println(senderAddress.getHostAddress().toString() + 
        " to " + addr.getHostAddress().toString()); 
       byte[] data = packetToReceive.getData(); 
       packetToReceive.setData(data, 0, packetToReceive.getLength()); 
       packetToReceive.setAddress(addr); 
       listenerSocket.send(packetToReceive); 
      } 
     } 
    } catch (IOException) { 
     e.printStackTrace(); 
    } 
} 

андроида логика отправитель:

mainSocket=new DatagramSocket(homePort); 

//targetAddressString is the public IP of server 
target = InetAddress.getByName(targetAddressString); 
while (true) { 
    byte[] data = getdata(); 
    if (data == null) 
     continue; 
    DatagramPacket packet = new DatagramPacket(data, data.length, target, targetPort); 

    mainSocket.send(packet); 
} 

тем временем на другом потоке, приемник просто ждет с таким же UdP гнездо:

while (true) { 
    Log.d("Player", "Waiting for data"); 
    DatagramPacket packet = new DatagramPacket(new byte[2048], 2048); 
    try { 
     mainSocket.receive(packet); 
     Log.d("Player", "packet received"); 
     //do something with the packet 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Он никогда не двигается дальше, чем ожидает данных, так как он будет блокироваться до тех пор, ceives пакет,

Кроме того, я могу также увидеть его в Wi-Fi и мобильных иконками данных, что никакие данные не когда-либо получал, но данные отправка всегда и считается полученным на сервере

** EDIT: - Echo сервер **

while (true) { 
    DatagramPacket receivedPacket = new DatagramPacket(new byte[2048], 2048); 
    try { 
     listenerSocket.receive(receivedPacket); 
     InetAddress senderAddress = receivedPacket.getAddress(); 
     if (!connectedClients.contains(senderAddress)) { 
      connectedClients.add(senderAddress); 
     } 

     for (InetAddress addr : connectedClients) { 
      byte[] data = receivedPacket.getData(); 
      DatagramPacket sendPacket= new DatagramPacket(data, 0, receivedPacket.getLength(), addr, receivedPacket.getPort()); 
      listenerSocket.send(sendPacket); 
     } 
    } catch (IOException e) { 
     // ... 
    } 
} 

в основном он должен передать сообщение для каждого клиента, который когда-либо посланного какие-либо данные, но как-то он посылает только его своему исходному отправителю остальную часть клиентов пропустить. код троллинг со мной

+1

Здесь что-то действительно магическое, я упростил сервер, чтобы просто потушить данные от одного клиента каждому в связанном клиенте. Тем не менее, только тот, кто первоначально отправил пакет, может вернуть его обратно. Думаю, я сделал очень глупую ошибку. – Allahjane

+0

Можете ли вы опубликовать код сервера как эхо-сервер, который работает? Это может дать нам необходимую информацию для ответа. –

+1

@ AlainO'Dea уверен, пожалуйста, см. Ediit – Allahjane

ответ

3

Это проблема обхода NAT, как вы поняли.

Вот несколько советов:

  1. Сервер может быть жестко вписан прослушивать порт 2706. Но он не должен делать никаких предположений о том, что порт источника принятых пакетов. Из вашего кода это выглядит не так, как вы когда-либо пытались позвонить setPort.Поэтому, даже если NAT не сопоставлял ваш номер порта по-разному, я не уверен, как ваш исходный код даже получал какой-либо порт назначения назначения. Но я думаю, вы поняли это на основе своего собственного ответа и вашего обновленного кода.

  2. Не переустанавливайте порт клиента на разъем клиента. Выберите порт «0» (или не установите его) в гнездо, чтобы ОС выбрала для вас первый доступный порт. Если у вас несколько клиентов за одним NAT, такое поведение позволит быстрее перезагрузить клиент, несколько устройств за одним NAT и другие приятные вещи.

+0

@ user1062760 Я считаю, что это правильный ответ, и вы должны его принять. –

+0

Да, спасибо, на самом деле 2706 был номером тестового номера, чтобы узнать, все ли прошло, и это было мое невежество, думая, что у моего мобильного телефона был публичный IP-адрес, который был фактической проблемой, но да, я должен был позволить os привязать его к доступный порт вместо жесткого кодирования, который работал бы, даже если я не знал бы: P – Allahjane

+0

есть ли способ заставить устройство прослушивать конкретный порт для нашего приложения для Android? –

2

Холли Молли! Я, наконец, понял, что это была моя собственная ошибка, я не рассматривал Nat Nat своего мобильного телефона и принимал 2706 портов в публичном IP.

Оказывается, на самом деле я был под NAT сети моего мобильного телефона, и мой порт 2706 был преобразован в какой-то отвратительный номер порта к тому времени, когда он достиг сервера. Поэтому мне пришлось рассматривать порт no фактического полученного пакета, а не тот, который установлен на телефоне.

В двух словах это было как этот

мобильного телефона (порт 2706) -> NAT (порт 40234) -> Сервер (порт 40234)

и поэтому я был на самом деле пытается отправить данные обратно в 2706 вместо 40234 -_- '

После того, как я начал отправлять обратно пакеты с номером 40234 (или что-то еще с пакетом) вместо 2706, он изящно следовал по пути обратно к моему мобильному телефону Android, и все было в порядке.

+0

есть ли способ, который мы могли бы получить с тем же портом, который отправляет сервер? –

+0

как изменение порта устройства для конкретного приложения в виде жесткокодированного порта? –

+0

уверен, что вы можете использовать один порт для передачи и приема данных без какой-либо уникальной удаленной адресации – Allahjane

Смежные вопросы