레이블이 network인 게시물을 표시합니다. 모든 게시물 표시
레이블이 network인 게시물을 표시합니다. 모든 게시물 표시

2015년 5월 8일 금요일

android java local network에서 다른 device를 찾는 방법 (UDP broadcast 하기)


java or android로 local network으로 하는 다중 접속 게임을 만들때 어떻게하면 같은 network에 있는 사용자를 찾을 수 있을까 고민해 보았습니다.

나와 같은 고민을 한사람들이 있었으니, 이걸 discover란 주제로 검색하면 많은 자료를 볼수 있었습니다.

여기 저기 찾아보니 UDP broadcast를 해서 받으면 된다고 합니다.
http://rocknirmana.blogspot.kr/2013/08/sending-udp-broadcast-socket-messages.html
원리는 각각의 어떤 node들이 있는지 모르니 새로들어온 node가 network broadcast를 하면 응답을 받는 쪽에서 새로운 node가 들어왔는구나 생각하고 접속을 시도하는 방법이 있을 수 있습니다.

여기에서는 PC와 android app간에 UDP broadcast의 테스트 예제를 해보았습니다.

보내는 PC 쪽 소스입니다.


public class UdpTestSend {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  String messageStr="Hello ! This is your msg from server.";
  int server_port = 50008; //port that I’m using
  try{
   DatagramSocket s = new DatagramSocket();
   InetAddress local;
   int msg_length=messageStr.length();
   byte[] message = messageStr.getBytes();
   
   byte[] ipAddr = new byte[] { -1, -1, -1, -1 };
   local = InetAddress.getByAddress(ipAddr);
   
   DatagramPacket p = new DatagramPacket(message, msg_length,local,server_port);
   s.send(p);
   System.out.println("message send");
  }catch(Exception e){
   System.out.println("error  " + e.toString());
  }
 }
}

server_port는 임의의 port입니다. 즉 node이 UDP 응답을 기다리는 port번호입니다. 따라서 받는쪽 코드도 같은 port이어야 합니다.
local 의 주소를 -1,-1,-1,-1 을 입력하였는데, 255.255.255.255로 모든 ip로 broadcast하게 됩니다.
http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node19.html 참고
INADDR_BROADCAST address (255.255.255.255)
보내는쪽 코드는 DatagramPacket, DatagramSocket class 두개만 천천히 살펴보면 됩니다.



이번에는 수신측 코드 입니다.
기본적으로 app을 만들고 아래 action_testudpbroadcast 조건의 타는 코드가 실행될수 있도록 작업합니다.


public class MainActivity extends Activity {

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

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  int id = item.getItemId();
  if (id == R.id.action_settings) {
   return true;
  }
  if (id == R.id.action_testudpbroadcast) {
   Log.d("test","start udp server");
   new Thread( new Runnable(){
    public void run(){
     String text;
     int server_port = 50008; 
     byte[] message = new byte[1500];
     try{
      DatagramPacket p = new DatagramPacket(message, message.length);
      DatagramSocket s = new DatagramSocket(server_port);
      s.receive(p);
      text = new String(message, 0, p.getLength());
      Log.d("test","message:" + text);
      s.close();
     }catch(Exception e){
      Log.d("test","error  " + e.toString());
     }
    }
   }).start();
   return true;
  }
  return super.onOptionsItemSelected(item);
 }
}


그리고 AndroidManifest.xml 에 아래 항목을 추가해야 합니다.

    <uses-permission android:name="android.permission.INTERNET"/>


실행방법
단말에서 TestApp을 실행시키고 해당 코드가 실행되게되게 해놓고, PC의 UdpTestSend를 실행하면 TestApp에서 message가 나오게 되면서 thread가 종료하게 됩니다.

05-08 21:26:50.598: D/test(15411): start udp server
>>>> 여기까지 대기하고 있다가 PC용 send를 시행시키면 아래 로그가 나오게 됩니다.

05-08 21:27:24.598: D/test(15411): message:Hello ! This is your msg from server.



참고 출처
http://www.java2s.com/Tutorials/Java/java.net/InetAddress/Java_InetAddress_getByAddress_byte_addr_.htm
http://stackoverflow.com/questions/13198669/any-way-to-discover-android-devices-on-your-network
https://code.google.com/p/boxeeremote/wiki/AndroidUDP
https://code.google.com/p/boxeeremote/source/browse/trunk/Boxee+Remote/src/com/andrewchatham/Discoverer.java?spec=svn28&r=28
http://rocknirmana.blogspot.kr/2013/08/sending-udp-broadcast-socket-messages.html
http://stackoverflow.com/questions/11273197/error-message-java-net-socketexception-socket-failed-eacces-permission-denie