검색결과 리스트
글
같은 공유기에 접속중인 안드로이드 기기 탐색 및 통신하기
안드로이드 디바이스와 같이 휴대용 기기의 경우 Wi-Fi를 사용할 때 장소 및 환경에 따라 항상 같은 공유기를 사용할 수 만은 없지요. 또한 무선공유기(라우터)에 접속할 때 마다 할당 받는 IP 주소 또한 달라질 수 있기 때문에 Socket 통신을 하게 될 때 IP 주소를 고정 시킬 수 없어 변경된 IP 주소를 일일이 변경하여야만 합니다.
그렇다면 번거롭게 IP 주소를 확인해야만 하는 걸까요? JAVA를 기반으로 하는 서버를 통한 통신 프로그래밍을 설계한다면 UDP 방식을 활용한 Broadcast 방식으로 공유기에 접속한 안드로이드 기기의 IP 주소를 알아낸 후 해당 IP를 통해 TCP 소켓 통신을 하는 방법이 있습니다.
이번 포스팅에서는 같은 공유기(라우터)에 접속중인 서버가 UDP를 통해 현재 접속 중인 안드로이드 기기들을 탐색한 후 이에 응답을 한 안드로이드 기기의 IP 주소를 통해 TCP 방식의 Socket 통신이 이루어지는 과정에 대해 알아보도록 하겠습니다.
본 포스팅의 소스코드는 이전에 작성하였던 아래 포스팅의 소스코드를 사용하였음을 밝힙니다. 혹시 서버에서의 UDP 통신에 대해 좀 더 알고 싶으신 분은 아래의 포스팅을 참조해 주시면 도움이 될 것입니다.
[JAVA] 같은 공유기에 접속중인 기기의 IP 주소 확인하는방법
-Server측(PC)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub RecvMesage rm = new RecvMessage(); rm.start(); for (int i = 0; i < 100; i++) { try { new SearchDevice("255.255.255.255", 8200).start(); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } rm.closeServer(); } static class SearchDevice extends Thread { InetAddress ia; int port; SearchDevice(String IPaddr, int Port) { try { ia = InetAddress.getByName(IPaddr); port = Port; } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { String msg = "Hello, ELECS!"; try { DatagramSocket ds = new DatagramSocket(); int length = msg.length(); byte[] msgbyte = msg.getBytes(); DatagramPacket dp = new DatagramPacket(msgbyte, length, ia, port); //UDP 방식으로 공유기에 접속중인 모든 기기에 Packet을 전송합니다. ds.send(dp); ds.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } static class RecvMessage extends Thread { boolean ready = true; Socket socket; InputStream is; ObjectInputStream ois; String clientIp; ServerSocket sockserver; Object lock = new Object(); public void closeServer() { try { synchronized (lock) { sockserver.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { try { sockserver = new ServerSocket(8000); while (ready) { //안드로이드 디바이스로부터 TCP 소켓 통신을 시작합니다. socket = sockserver.accept(); synchronized (lock) { is = socket.getInputStream(); ois = new ObjectInputStream(is); //안드로이드 기기로부터 IP주소를 받아옵니다. clientIp = (String) ois.readObject(); System.out.println("Client IP : " + clientIp); ois.close(); is.close(); socket.close(); } } } catch (SocketException e) { System.out.println("ServerSocket is closed!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } | cs |
-Client측(안드로이드 디바이스)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | public class MainActivity extends AppCompatActivity { TextView tv1; Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv1 = (TextView)findViewById(R.id.textview1); (new RecvUDP()).start(); } class RecvUDP extends Thread{ String text; String serverIp; DatagramPacket dp; public void run(){ int port = 8200; byte[] message = new byte[1000]; dp = new DatagramPacket(message, message.length); try { DatagramSocket ds = new DatagramSocket(port); //서버로부터 전달되는 Packet을 수신합니다. ds.receive(dp); text = new String(message, 0, dp.getLength()); ds.close(); //수신된 Packet으로부터 서버의 IP를 저장합니다. serverIp = dp.getAddress().getHostAddress(); mHandler.post(new Runnable(){ @Override public void run() { tv1.setText(text); } }); WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiMgr.getConnectionInfo(); int ip = wifiInfo.getIpAddress(); String androidIp = Formatter.formatIpAddress(ip); //서버의 IP를 통하여 Socket 통신을 시작합니다. Socket sock = new Socket(serverIp, 8000); DataOutputStream os = new DataOutputStream(sock.getOutputStream()); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(androidIp); oos.close(); os.close(); sock.close(); } catch (Exception e) { e.printStackTrace(); } } } } | cs |
-결과
'안드로이드 > 애플리케이션 제작' 카테고리의 다른 글
안드로이드 - Java 서버간 Object 객체 소켓 프로그래밍 (8) | 2015.10.29 |
---|---|
Linux(우분투)에서 Android Studio 빠르게 실행하는 방법(바로가기 추가하기) (0) | 2015.10.17 |
Error: The SDK Build Tools revision is too low for project (0) | 2015.10.10 |
저장된 사진및 파일이 보이지 않을 때 미디어스캐닝(Media Scanning) 방법 [Kitkat 이후의 버전에서 적용방법] (0) | 2015.10.04 |
byte[] 바이트 배열을 socket을 통해 쉽게 전송하는 방법 (0) | 2015.10.03 |
설정
트랙백
댓글
글
[JAVA] 같은 공유기에 접속중인 기기의 IP 주소 확인하는방법
TCP를 통해 Socket 통신을 하기 위해서는 접속하고자 하는 기기에 할당된 IP주소를 알고 있어야 합니다. 다시 말하자면, IP 주소를 알지 못할 경우 TCP를 통해서는 기기간의 통신이 불가능하다는 것입니다.
그렇다면 상대의 IP 주소를 알아낼 수 있는 방법은 없는 것일까요? IP 프로토콜 규약에 의하면 특수 IP 주소를 사용하면 다른 기기와 통신이 가능하도록 설정되어 있습니다. 예를 들어 '255.255.255.255' 주소로 패킷을 보내면 같은 라우터(공유기) 내에 연결된 모든 기기들이 이를 수신하게 됩니다. 이를 Broadcast라고 칭하며 이를 사용하기 위해서는 TCP가 아닌 UDP 방식을 사용하여야 합니다.
아래의 소스코드는 UDP 방식을 사용하여 서버가 IP주소 '255.255.255.255'를 통해 같은 라우터(공유기) 내에 접속중인 기기들에게 패킷을 보낸 후 이를 수신한 기기가 자신의 IP 주소를 서버에 알려주는 방식입니다.
- DatagramPacket가 상대에게 전송될 때 해당 패킷 안에는 패킷을 보낸 측의 IP 주소가 담겨 있습니다. 이를 통해 서버측 IP와 클라이언트측 IP를 서로 알 수 있습니다.
Server측
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub RecvServer rm = new RecvServer(); rm.start(); for (int i = 0; i < 10; i++) { try { new SearchDevice("255.255.255.255", 8200).start(); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } rm.closeServer(); } static class SearchDevice extends Thread { InetAddress ia; int port; SearchDevice(String IPaddr, int Port) { try { ia = InetAddress.getByName(IPaddr); port = Port; } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { String msg = "Hello, ELECS!"; try { DatagramSocket ds = new DatagramSocket(); int length = msg.length(); byte[] msgbyte = msg.getBytes(); DatagramPacket dp = new DatagramPacket(msgbyte, length, ia, port); ds.send(dp); ds.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } static class RecvServer extends Thread { String text; String clientIp; DatagramPacket dp; DatagramSocket ds; Object lock = new Object(); public void closeServer() { synchronized (lock) { ds.close(); } } public void run() { int port = 8000; byte[] message = new byte[1000]; dp = new DatagramPacket(message, message.length); try { ds = new DatagramSocket(port); ds.receive(dp); synchronized (lock) { text = new String(message, 0, dp.getLength()); ds.close(); clientIp = dp.getAddress().getHostAddress(); System.out.println("Client IP : " + clientIp); } } catch (Exception e) { e.printStackTrace(); } } } } | cs |
Client측
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub String text; String serverIp; DatagramPacket dp; int port = 8200; byte[] message = new byte[1000]; dp = new DatagramPacket(message, message.length); try { DatagramSocket ds = new DatagramSocket(port); ds.receive(dp); text = new String(message, 0, dp.getLength()); ds.close(); serverIp = dp.getAddress().getHostAddress(); new SearchDevice(serverIp, 8000).start(); } catch (Exception e) { e.printStackTrace(); } } static class SearchDevice extends Thread { InetAddress ia; int port; SearchDevice(String IPaddr, int Port) { try { ia = InetAddress.getByName(IPaddr); port = Port; } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { String msg = "Hello, ELECS!"; try { DatagramSocket ds = new DatagramSocket(); int length = msg.length(); byte[] msgbyte = msg.getBytes(); DatagramPacket dp = new DatagramPacket(msgbyte, length, ia, port); ds.send(dp); ds.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } | cs |
결과
'프로그래밍 팁' 카테고리의 다른 글
Fedora에 이전 버전의 OpenJDK 설치하기(Install OpenJDK 7 in Fedora 23) (0) | 2015.12.22 |
---|---|
OpenCV 최신 버전에서 Python으로 SIFT, SURF 사용하기(Install OpenCV 3.0 in Ubuntu) (2) | 2015.11.18 |
[JAVA] Socket 서버 구현시 안전하게 SocketServer를 종료하는 방법 (3) | 2015.10.14 |
[C/C++]thread 조건변수 다루기 - pthread_cond_broadcast() (0) | 2015.09.01 |
[JAVA]JDWP(Java™ Debug Wire Protocol) (0) | 2015.08.21 |
설정
트랙백
댓글
글
[JAVA] Socket 서버 구현시 안전하게 SocketServer를 종료하는 방법
안드로이드를 활용한 다양한 소켓 프로그래밍들의 에제를 둘러보다 보면 Server 측의 Socket을 다루는 데 종종 난해한 경우가 있습니다. 가령 Client측으로부터 Socket 통신이 한창 진행중인 상황에서 서버측 Socket을 닫아버리면 진행중이던 통신 관련 작업이 모두 끝나기도 전에 서버가 종료되어 버리는 심각한 상황이 발생할 수도 있는 것이지요.
본 포스팅에서는 Java를 활용한 서버측의 Socket을 좀 더 안정적으로 종료시키는 방법에 대해 알아보도록 하겠습니다.
- Client와 Socket 통신이 진행중인 상황에서 ServerSocket이 강제로 종료되지 않도록 하기 위해 synchronized를 사용합니다. 이는 C/C++에서 제공하는 Mutex와 유사한 역할을 합니다. synchronized() 의 인자(Argument)를 가지고 있는 쪽에서 실행을 하다가 종료가 되었을 때 이를 다른 쪽에서 점유한 후 실행이 종료될 때 까지 다른 부분에서는 실행되지 않도록 설정합니다.
- ServerSocket이 accpt()를 실행하던 중에 종료되었을 때 SocketException이 발생합니다. 이 때 try-catch를 통해 해당 Exception을 catch한 후 Server가 안전하게 종료되었음을 확인합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub RecvMessage rm = new RecvMessage(); //Server Thread를 실행합니다. rm.start(); .... //ServerSocket를 닫음으로서 Server Thread를 종료합니다. rm.closeServer(); } static class RecvMessage extends Thread { boolean ready = true; Socket socket; InputStream is; ObjectInputStream ois; String clientIp; ServerSocket sockserver; //Mutex로 사용할 Object 변수를 선언합니다. Object lock = new Object(); public void closeServer() { try { //Client와 Socket 통신이 진행중일 경우 종료될 때까지 기다립니다. synchronized (lock) { sockserver.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { try { sockserver = new ServerSocket(8200); while (ready) { socket = sockserver.accept(); //Client와의 통신이 종료될 때 까지 SocketServer의 종료를 보류시킵니다. synchronized (lock) { is = socket.getInputStream(); ois = new ObjectInputStream(is); clientIp = (String) ois.readObject(); System.out.println("Client IP : " + clientIp); ois.close(); is.close(); socket.close(); } } } catch (SocketException e) { //ServerSocket가 종료되었을 때 실행됩니다. System.out.println("ServerSocket is closed!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } | cs |
'프로그래밍 팁' 카테고리의 다른 글
OpenCV 최신 버전에서 Python으로 SIFT, SURF 사용하기(Install OpenCV 3.0 in Ubuntu) (2) | 2015.11.18 |
---|---|
[JAVA] 같은 공유기에 접속중인 기기의 IP 주소 확인하는방법 (0) | 2015.10.15 |
[C/C++]thread 조건변수 다루기 - pthread_cond_broadcast() (0) | 2015.09.01 |
[JAVA]JDWP(Java™ Debug Wire Protocol) (0) | 2015.08.21 |
[Java] Error 혹은 Debug시 등장하는 method인 access$000 (0) | 2015.08.20 |