Site Search :
Standard Enterprise XML Methodology Pattern Setting Tunning Other
Article Contributors
GuestBook
Javapattern Maven
XSourceGen Dev
JetSpeed Test
JLook Image
jLook Family Site


DatagramSocket의 정의 및 샘플
 
UDP의 기본개념을 알아보고 데이터그램 소켓 및 패킷에 대하여 알아보며 간단한 서버 및 클라이언트 프로그램을 작성해보도록 하자. ( 2003/09/01 ) 169
Written by ienvyou - 최지웅
1 of 1
 
 UDP(User Datagram Protocol)

UDP(User Datagram Protocol)는 인터넷에 있어 datagram을 전송하는 전송층 프로토콜인 것은
사실이지만 TCP 처럼 그 사양이 엄격하게 정의된 것은 아닙니다. 
UDP 는 비연결기반형인데, 이러한 비연결성(connectionless) 은 IP 프로토콜의 특징이기도 합니다. 
또한 UDP 의 데이터 패킷인 데이터그램 패킷은 그 헤더에 소스 포트(로컬 포트)와 목적지 포트(원거리 포트) 
그리고 데이터그램 패킷 길이, 체크섬 정도만 갖습니다. 그런데 자바의 데이크그램 패킷은 IP 어드레스
정보도 포함하고 있어 데이터그램 패킷에 대한 IP 패킷에 더 가깝습니다. 

<표 1>   UDP Datagram 형식
Source Port(로컬포트)Destination Port(원거리포트)
LengthChecksum
Data
TCP 프로그래밍과 데이터 프로그래밍의 차이 <표 2>
 TCP 프로그래밍Datagram 프로그래밍
소켓의 종류접속 요청용 : ServerSocket 통신용 : Socket 구분없이 DatagramSocket만 사용
전달 데이터 유형미가공 데이터Datagram Packet
소켓의 종류 TCP 프로그래밍에서는 클라이언트로부터의 접속요청을 듣는 서버 소켓(ServerSocket 개체)과 클라이언트와 상호 통신을 담당하는 클라이언트 소켓(Socket 개체)이 구분되어 있었습니다. 그러나 데이터그램 프로그래밍에서는 서버소켓이 따로 없고 클라이언트 소켓에 해당하는 DatagramSocket 개체만이 있습니다. 이는 당연한 것이 UDP 프로그래밍은 비연결형이므로 접속을 당당할 서버소켓이 필요없는 것입니다. 그러니까 데이터그램 프로그래밍에서는 클라이언트의 접속을 허용하고 어쩌고 할 것 없이 데이터그램 소켓 하나로 무조건 데이터그램 패킷을 읽고 씁니다. 물론 보안관리자가 없을 때 그렇습니다. 보안관리자가 설치되어 있으면 보안 검사 정도는 합니다. ▶ 전달 데이터 유형 TCP 프로그래밍(혹은 소켓 프로그래밍)에서는 전달하는 데이터가 우리가 프로그래밍에서 일상적으로 다루는 유형과 다를 바 없었습니다. 즉, 입출력스트림이 다룰 수 있는 데이터라면 TCP 프로그래밍에서도 전송할 수 있었습니다. 이 말이 TCP에서 전달 데이터 유형이 그렇다는 것이 아니라 TCP 애플리케이션에서 그렇다는 것입니다. 우리가 TCP 애플리케이션에서 다른 것은 신경쓰지 않고 출력스트림으로 일반 데이터를 보내면, 그 아래층인 TCP 및 IP 층을 통과하면서 패킷화됩니다. 그러니까 TCP 프로그래밍은 철저하게 애플리케이션층만 담당합니다. 그러나 데이터그램 프로그래밍에서는 미가공 데이터를 그대로 보내지 않고, 먼저 데이터그램 패킷으로 변환한 뒤 이를 입출력스트림을 통해 전송합니다. 그런데 자바의 데이터그램 패킷은 순수한 데이터그램 패킷이 아닌 IP 패킷 특성도 포함한 그런 것입니다. 그러니까 자바 데이터그램 프로그래밍은 애플리케이션층만 담당하는 것이 아니라 그 아래층인 전송층, 심지어는 네트웍층까지도 직접 건드립니다. ▶DatagramSocket 클래스 정의 DatagramSocket 클래스- DatagramPacket 객체를 전송하고 수신하는데 사용할 수 있는 데이터그램 소켓 클래스 입니다. * 생성자 DatagramSocket() throws SocketException - 포트 번호가 임으로 정해진 상태의 DatagramSocket 객체를 생성 DatagramSocket(int port) throws SocketException - 매개변수로 들어온 port에서 대기하는 DatagramSocket 객체를 생성 DatagramSocket(int port, InetAddress Iaddr) throws SocketException - 매개변수로 들어온 port에서 대기하는 DatagramSocket 객체를 생성하여 해당 IP 어드레스에 바인딩 합니다.이 생성자는 다중 IP 어드레스를 갖는 호스트에서 사용합니다. ▶ DatagramPacket 클래스 정의 DatagramPacket은 UDP 통신에서 데이터의 패킷을 만들어 DatagramSocket을 이용해서 송,수신 할 수 있는 기능을 제공합니다. public DatagramPacket(byte buffer[ ], int length) - 데이터를 받기 위해 DatagramPacket 객체를 만드는 생성자 - buffer[ ]: 데이터가 위치해 있는 바이트 배열 - length: 버퍼의 길이 public DatagramPacket(byte buffer[ ], int length, InetAddress ia, int port) - 다른 호스트로 전송할 DatagramPacket 생성하는 생성자 - buffer[ ]: 전송할 데이터의 바이트 배열 - length: 버퍼의 길이 - InetAddress ia: 패킷의 목적지 호스트 주소 - Port: 목적지 포트 번호 ▶ Datagram Server작성예

import java.net.*;

public class DaytimeServer {
  public static final int DEFAULT_PORT = 13;
  public static void main (String[] args) throws IOException {
    if (args.length > 1)
      throw new IllegalArgumentException ("Syntax: DaytimeServer []");
    // 사용자 입력 포트의 DatagramSocket 생성 입력값이 없을 경우 Default Port 13
    DatagramSocket socket = new DatagramSocket
      (args.length == 0 ? DEFAULT_PORT : Integer.parseInt (args[0])); 
    DatagramPacket packet = new DatagramPacket (new byte[1], 1); // DatagramPacket 생성

    while (true) {
      socket.receive (packet); // 소켓으로부터 패킷을 받음
      System.out.println
        ("Received from: " + packet.getAddress () + ":" + packet.getPort ());
     
      byte[] outBuffer = new java.util.Date ().toString ()
        .getBytes ("latin1"); // 패킷 정보를 표시
      packet.setData (outBuffer);
      packet.setLength (outBuffer.length);
      socket.send (packet); 
    }
  }
}

데이터임 서버는 명령행 인자로 설정된 포트에서 대기하면서, 들어오는 모든 패킷에 대해 현재 시간을 담아 클라이언트에 응답합니다. 패킷 수신과 응답에는 하나의 스레드만 사용하였습니다. Main()메소드에서는 우선 인자로 설정된 포트 번호가 제대로 된 것인지 검증하고, 그렇지 않은경우 디폴드 포트 번호인 13을 사용합니다.그리고 DatagramSocket타입의 Socket을 생성하고 이 포트에서 대기시킨 후 UDP 패킷을 받을 때 사용할 DatagramPacket 타입의 Packet을 생성합니다. 이 프로그램의 핵심인 루프 부분에서는 receive()를 호출하여 패킷이 오기를 기다리며, 패킷이 오면 이 패킷을 보낸 호스트 정보를 출력한 후에 현재의 날짜와 시간 정보가 담긴 바이트 배열인 outBuffer를 새로 만듭니다. packet 객체의 setData()와 setLength()를 사용하여 receive()로 받은 패킷에 시간정보를 넣습니다. 마지막으로 send()메소드를 호출하여 원래의 호스트로 packet을 돌려 보냅니다. == 참고 == packet에는 원래 호스트 주소와 포트번호가 이미 들어 있기 때문에, packet정보는 그냥 놔두어도 된다. ▶ Datagram Client 작성예

import java.net.*;

public class DaytimeClient {
  public static void main (String[] args) throws IOException {
    if ((args.length != 1))
      throw new IllegalArgumentException
        ("Syntax: DaytimeClient [:]");
 
    int idx = args[0].indexOf (":");
    int port = (idx > -1) ? Integer.parseInt (args[0].substring (idx + 1))
      : DaytimeServer.DEFAULT_PORT;
    String hostName = (idx > -1) ? args[0].substring (0, idx) : args[0];
    InetAddress host = InetAddress.getByName (hostName);
 
    DatagramSocket socket = new DatagramSocket ();
    socket.setSoTimeout (5000);
    DatagramPacket packet = new DatagramPacket (new byte[256], 1, host, port);
    socket.send (packet);
    packet.setLength (packet.getData ().length);
    socket.receive (packet);
    socket.close ();
 
    byte[] data = packet.getData ();
    int length = packet.getLength ();
    System.out.println (new String (data, 0, length, "latin1"));
  }
}}

DaytimeClient 는 DaytimeServer를 테스트 하기 위한 것입니다. 매개변수로 설정된 컴퓨터 포트에 패킷을 보내고, 응답을 기다리고, 받은 응답 정보의 내용을 출력하는 것이 전부입니다. Main()메소드 에서는 호스트 주소인 host와 포트 번호를 검사하여, 역시 포트번호가 주어지지 않으면 디폴트 포트 번호를 사용합니다. 패킷을 보낼 준비를 하기 위해 5초의 수신 타임아웃이 설정된 DatagramSocket타입의 소켓을 생성하고 테이터 길이가 1이고 리모트 서버의 주소가 담긴 256바이트의 버퍼를 넣어 DatagramPacket 타입의 패킷을 생성합니다. Send()를 통해 보내지는 패킷은 단 한 바이트를 보내지만 응답을 받기에는 충분합니다. 패킷을 보내고 나면 즉시 이 패킷의 페이로드를 256으로 재설정하여 응답을 기다리기 때문에 , 받아들일 수 있는 응답 정보의 길이는 최대 256 이 됩니다. 만약 수신시간 5초를 넘기면 InterruptedIOException예외와 함께 프로그램 실행이 바로 멈춥니다. 간단하게 Datagram에 대하여 알아보았으며, 다음 아티클은 멀티캐스트에 대하여 알아보도롭 합니다.
 
1
References
 
java network programming : 한빛미디어
Copyright ⓒ 2003 www.javapattern.info & www.jlook.com, an jLOOK co.,LTD