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