해당 포스트는 "안드로이드 통신+보안 프로그래밍" 책의 내용을 요약한 것이다.



※ UDP 프로그램 작성

: UDP 프로그래밍은 TCP 프로그래밍에서의 ServerSocket, Socket 객체 대신 DatagramSocket 객체를 사용하고 스트림 객체 대신 DatagramPacket 객체를 사용한다. UDP 프로그래밍 하는 방법에 대해서 알아보자.


1. DatagramSocket 인스턴스 생성

: DatagramSocket(int port) 또는 DatagramSocket(int port, InetAddress laddr) 생성자로 객체를 생성한다.


2. DatagramPacket 인스턴스 생성

: 데이터의 송수신을 위해 DatagramPacket 인스턴스를 만든다. 수신용 DatagramPakcet은 DatagramPacket(byte buf[], int length) 생성자를 사용하면 된다. 송신용 DatagramPacket은 추가로 목적지의 IP와 포트번호를 매개변수로 줘야 한다.

3. DatagramPacket을 통한 데이터 송수신

: receive(DatagramPacket p) 메서드를 통해 데이터를 수신한다. 데이터가 수신될 때까지 블록상태를 유지하고 DatagramPacket을 생성할 때 인자로 줬던 length 보다 큰 데이터는 수신 불가능하다. 만약 데이터가 length보다 큰 경우 length크기 만큼만 수신되고 나머지는 삭제된다. 추가로 보안매니저가 설정되어 있으면 보안매니저가 허용하지 않는 수신처로부터의 패킷은 삭제된다. 데이터를 송신할 때는 send(DatagramPacket p) 메서드를 사용한다. 


4. DatagramSocket Close

※ UDP 서버 프로그램 구현

public class UDPEchoServer { public static void main(String[] args){ Thread t= new Thread(new UDPServer()); t.start(); try{ //메인 스레드가 종료되지 않도록 join을 호출 t.join(); }catch(Exception e){ e.printStackTrace(); } } } class UDPServer implements Runnable{ public static final int SERVERPORT = 5000; private Boolean loop; private DatagramPacket dp = null, packet; private DatagramSocket ds = null; @Override public void run(){ byte[] buffer = new byte[2048]; try{ ds = new DatagramSocket(SERVERPORT); System.out.println("Starting....."); ds.setSoTimeout(10000); //수신용 데이터 패킷 생성 dp = new DatagramPacket(buffer, buffer.length); loop = true; }catch(SocketException e){ System.out.printf("S: Error", e); e.printStackTrace(); loop=false; } System.out.println("ready"); while(loop){ try{ ds.receive(dp); if(dp.getData()!=null){ String str = new String(dp.getData()).trim(); System.out.println("수신된 데이터 : "+str); InetAddress ia = dp.getAddress(); int port = dp.getPort(); byte[] s = str.getBytes(); packet = new DatagramPacket(s, s.length, ia, port); ds.send(packet); } //buffer을 재사용하기 위해 리셋 Arrays.fill(buffer, (byte)0); }catch(SocketTimeoutException e){ }catch(SocketException e){ }catch(Exception e){ System.out.printf("S: Error\n",e); e.printStackTrace(); } } } public void quit(){ loop = false; ds.close(); } }

위에서 데이터 패킷을 수신하고 String 객체로 바꿀 때 trim을 사용했다. UDP를 통해 데이터 패킷을 수신할 때 데이터를 구분하기 위해서 데이터의 끝에 null을 사용한다. 그래서 자바는 null을 String으로 만들 때 유니코드로 만들기 때문에 수신된 데이터 패킷을 String 객체로 만든다면 null을 포함한 쓰레기 데이터도 들어간다. 따라서 trim 메서드를 이용해서 null 값을 없애야 한다. 또한 setSoTimeout 메서드를 통해 receive에서 무한정 대기하는 걸 막았다.

UDP를 이용한 안드로이드 클라이언트 프로그램은 UDP 서버 프로그램과 비슷한 부분이 많고 이전 포스트에서 배운 내용을 토대로 구현 가능할 것이라 생각해 생략한다.


※ 브로드 캐스트 통신

: UDP 통신의 특징 중 하나로 브로드 캐스트가 있다. 브로드 캐스트는 같은 네트워크 안에 있는 모든 호스트에 데이터를 보내는 것이다. 만약 네트워크 주소로 "192.168.1.0/24"를 사용한다고 하면 "192.168.1.255"를 목적지 주소로 한 데이터를 보내면 "192.168.1.1"~"192.168.1.254"에 해당하는 모든 호스트에 데이터가 전달된다. 브로드 캐스트는 특정 기능을 하는 서버를 찾거나 프린터와 같은 특수 목적의 장비를 찾고자 할 때 사용한다. IPV6의 경우 브로드캐스트가 지원되지 않아 브로드캐스트를 멀티 캐스트를 이용해 해야 한다.

브로드 캐스트 통신을 하려면 DatagramSocket 객체의 setBroadcast(true)를 호출해야 한다. 구현 방법은 위에서 본 UDP 프로그램과 다른 게 없다. 단지 목적지 IP를 브로드캐스트 IP로 주고 setBroadcast(true)를 호출하는 것만 다르다.




+ Recent posts