2013-02-16 2 views
4

현재 Java에서 UDP 패킷 전송을 탐색하여 Android에서 멀티 플레이어 게임을 만들고 있습니다. 일반적인 "127.0.0.1"을 사용하여 Nexus 4에서 패킷을 교환하는 데 성공했으며 내 로컬 네트워크에서 내 PC 서버와 Android 클라이언트간에 패킷을 교환하는 데 성공했습니다. 하지만 내 게임을 인터넷에서 재생할 수 있기를 원하므로 Android 클라이언트가 동일한 로컬 네트워크에 있지 않을 때 내 PC 서버와 패킷을 교환 할 수 있기를 바랍니다. 이것은 내가 고심하고있는 곳이다.인터넷을 통해 PC 서버에서 Android에 UDP 데이터를 수신 할 수 없습니다.

내 설정 : 집에 인터넷에 연결된 PC 서버와 3G 네트워크에 연결된 Nexus 4.

먼저 내 PC 서버는 포트 10000에서 수신을 시작하고 Android 클라이언트는 포트 10001에서 서버의 패킷을 수신하기 위해 소켓을 엽니 다. 그런 다음 Android 클라이언트는 패킷을 PC 서버에 현재 공용 주소 "173.246"로 보냅니다. 12.125 "로 설정합니다. PC 서버는 패킷을 수신하고 포트 10001에서 보낸 사람에게 응답을 보냅니다. 그러나 안드로이드 클라이언트는 응답을 수신하지 않습니다.

public class UDPServer { 
    private final static int SERVER_PORT = 10000; 
    private final static int CLIENT_PORT = 10001; 

    public static void main(String[] args) { 
     InetAddress clientAddr = null; 
     DatagramSocket socket = null; 
     try { 
      //Initializing the UDP server 
      System.out.println(String.format("Connecting on %s...", SERVER_PORT)); 
      socket = new DatagramSocket(SERVER_PORT); 
      System.out.println("Connected."); 
      System.out.println("===================="); 
     } catch (UnknownHostException e1) { 
      e1.printStackTrace(); 
     } catch (SocketException e) { 
      e.printStackTrace(); 
     } 

     while(true){ 
      try { 
       //Listening 
       byte[] buf = new byte[1024]; 
       DatagramPacket packet = new DatagramPacket(buf, buf.length); 
       System.out.println("Listening..."); 
       socket.receive(packet); 

       //Getting client address from the packet we received 
       clientAddr = packet.getAddress(); 
       System.out.println("Received: '" + new String(packet.getData()).trim() + "' from "+clientAddr.toString()); 

       //Sending response 
       byte[] message = ("Hello Android").getBytes(); 
       DatagramPacket response = new DatagramPacket(message, message.length, clientAddr, CLIENT_PORT); 
       DatagramSocket clientSocket = new DatagramSocket(); 
       System.out.println("Sending: '" + new String(message) + "'"); 
       clientSocket.send(response); 
       System.out.println("Response sent."); 
       System.out.println("--------------------"); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

그리고 여기 내 안드로이드 클라이언트 클래스입니다 : 여기

내 PC 서버 코드

public class MainActivity extends Activity { 

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

     new Thread(new Receiver()).start(); 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     new Thread(new Client()).start(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 

} 

public class Receiver implements Runnable { 
    private final static int LISTENING_PORT = 10001; 

    @Override 
    public void run() { 
     try { 
      //Opening listening socket 
      Log.d("UDP Receiver", "Opening listening socket on port "+LISTENING_PORT+"..."); 
      DatagramSocket socket = new DatagramSocket(LISTENING_PORT); 
      socket.setBroadcast(true); 
      socket.setReuseAddress(true); 

      while(true){ 
       //Listening on socket 
       Log.d("UDP Receiver", "Listening..."); 
       byte[] buf = new byte[1024]; 
       DatagramPacket packet = new DatagramPacket(buf, buf.length); 
       socket.receive(packet); 
       Log.d("UDP", "Received: '" + new String(packet.getData()).trim() + "'"); 
      } 
     } catch (Exception e) { 
      Log.e("UDP", "Receiver error", e); 
     } 
    } 
} 

public class Client implements Runnable { 
    private final static String SERVER_ADDRESS = "173.246.12.125";//public ip of my server 
    private final static int SERVER_PORT = 10000; 

    @Override 
    public void run() { 
     try { 
      //Preparing the socket 
      InetAddress serverAddr = InetAddress.getByName(SERVER_ADDRESS); 
      DatagramSocket socket = new DatagramSocket(); 

      //Preparing the packet 
      byte[] buf = ("Hello computer").getBytes(); 
      DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVER_PORT); 

      //Sending the packet 
      Log.d("UDP", String.format("Sending: '%s' to %s:%s", new String(buf), SERVER_ADDRESS, SERVER_PORT)); 
      socket.send(packet); 
      Log.d("UDP", "Packet sent."); 
     } catch (Exception e) { 
      Log.e("UDP", "Client error", e); 
     } 
    } 
} 

서버의 콘솔에서 클라이언트의 IP를 보여주고있다 :

Connecting on 192.168.1.126:10000... 
Connected. 
==================== 
Listening... 
Received: 'Hello computer' from /204.48.72.68 
Sending: 'Hello Android' 
Response sent. 
-------------------- 
Listening... 

패킷이 204.48.72.68 주소에서 온 것 같습니다.하지만 Android에서 whatismyip.com을 실행하면 m e 96.22.246.97 ... 204.48.72.68이 어디서 왔는지 모르겠다 ...

안드로이드 클라이언트의 수신 대기 소켓이 좋지 않거나 PC 서버 올바른 주소로 응답을 보내지 않습니다. 누군가 내가 뭘 잘못하고 있다고 지적 할 수 있습니까?

+0

http://developer.android.com/reference/android/app/Activity에 문제가 생겼을 수 있습니다.html # ProcessLifecycle –

+0

당신이 내게 말하는 내용을 이해한다면, 내 수신자가 새 스레드에서 실행 되더라도 응용 프로그램이 활동 작성시 메시지를 보내더라도 안드로이드는 생성 된 다음 ms 내에 내 수신자 프로세스를 죽일 수 있습니다. 활동? –

+0

나는 전문가는 아니지만 그런 일이있을 수 있습니다. 일부 출력물이나 디버깅이 유용 할 수 있습니다. –

답변

1

나는 비슷한 문제를 건너 왔어요 감사하지만 UDP 대신 TCP 소켓을 사용하고 있었다. 내 강렬한 파일을 모바일로 직접 보냈습니다. LAN에서 이것은 꽤 효과가있었습니다. 휴대 전화가 모바일 연결을 사용하여 인터넷에 연결되어있는 경우 수신 대기 소켓으로 데이터를 전송할 수 없습니다. 휴대 전화로 들어오는 연결이 통신 공급자에 의해 차단 된 일부 페이지 (더 이상 링크가 없습니다)를 읽었습니다. 이 문제를 해결하려면 서버로의 나가는 연결을 만들고 tcp 소켓의 양방향 가능성을 사용하십시오. 아마도 "작동하는"데이터 그램 소켓을 사용하여 모바일과 데이터를 교환 할 수 있습니다. 당신이 어떤 안드로이드 모바일을 사용하는 경우 에뮬레이터하지만 작품 벌금 시도 할 때 나를 위해 잘 작동 http://itucet.blogspot.de/2011/03/java-bidirectional-data-transfer-using.html

+0

응답 주셔서 감사합니다. 들어오는 연결을 차단하는 통신 공급자를 알지 못했습니다. TCP 연결은 살아 있기 때문에 사용할 수 있다는 것을 알고 있지만 더 빠른 패킷 교환을 위해 UDP를 사용하기로했습니다. 사용할 수있는 "작동중인"데이터 그램 소켓이 무엇인지 설명해 주시겠습니까? 추신 :이 예제는 단일 컴퓨터에서 서버와 클라이언트를 테스트 할 때 사용했던 예제입니다. –

+0

안녕하세요 컴퓨터를 서버에 보낸 것과 동일한 DatagramSocket을 다시 사용한다는 뜻입니다. 다른 스레드를 사용하고 있지만 동일한 소켓을 사용할 수 있습니다. 이것이 당신의 요구를 충족 시킬지 모르겠다. 나는 단지 그것을 염두에두고 싶다. – lunatikz

+0

나는 또한 http://stackoverflow.com/questions/5904820/android-udp-communication에서 그것을 읽었지만 나에게 도움이되지 못했다. 내 서버가받는 패킷의 IP 주소가 내 휴대 전화의 실제 IP 주소가 아니기 때문이라고 생각합니다. 통신 제공 업체의 인프라에 어딘가에 차단 기능이있는 것 같습니다. –

1

같은 코드는 문제 유무 : 여기에 내가 발견 한 예이다.

문제의 원인은 android 에뮬레이터이며 컴퓨터가 동일한 서브넷에 있지 않습니다.

+0

안드로이드 에뮬레이터를 사용하지 않고 있었는데, 문제는 안드로이드 휴대 전화가 연결된 네트워크가 내 서버가 설정하려고 시도했던 연결을 차단하고 있었다고 생각합니다. UPD는 모든 통신 네트워크에서 작동하지 않습니다. –

관련 문제