본문 바로가기

Master_branch/study_branch

Java UDP Client Server Program - UDP 프로그래밍

이번 포스팅에서는 UDP 프로토콜을 기반으로 클라이언트 / 서버 응용 프로그램 예제를 적어보려고 합니다.

 

 

 

Java UDP 클라이언트 - 서버 프로그램 예제

 

UDP 통신에서는 

  • DatagramPacket
  • DatagramSocket

이 두 가지 클래스가 주요하게 사용 됩니다.

DatagramPacket은 데이터를 담게 되고, DatagramSocket은 전송 / 수신 할 수 있는 메커니즘이라고 생각 하면 되겠습니다.

 

 

DatagramPacket

UDP에서 전송 된(전송 할) 데이터는 datagram 단위로 캡슐 화 됩니다. UDP 프로토콜의 특성을 그대로 가지고 있는 datagram 패킷은 데이터의 도착, 도착 시간 및 내용이 보장 되지 않는 네트워크를 통해 전송 되는 메시지 입니다.

DatagramPacket은 다음과 같은 생성자를 가지고 있습니다.

 

 

위의 생성자에서 보이듯이, 데이터는 byte[] array 형식이어야 합니다. 

A - 수신 할 DatagramPacket을 만드는 데에 사용 됨

B - 전송 할 DatagramPacket을 생성 하는 데에 사용 됨. 전송 대상 호스트의 주소와 포트 번호를 지정해야 함

C,D - SocketAddress를 사용하는 것 외에도 바이트 배열에서 오프셋을 지정 할 수 있는 생성자

 

 

DatagramSocket

 

Java에서는 UDP 통신에 클라이언트와 서버 모두에 DatagramSocket을 사용합니다.

 

다음 생성자 중 하나를 사용하여 Datagram 송수신을 위한 UDP 연결을 설정하는 객체를 만듭니다.

 

 

 

A - 임의의 포트 번호에 바인드 하는 클라이언트를 만드는 데 사용

B - 특정 포트번호에 바인딩 하는 서버를 만드는 데 사용

C - 서버에 지정 된 IP 주소를 바인딩 (컴퓨터에 여러 IP 주소가 있는 경우)

 

A,B,C 모두 포트나 주소에 바인딩 할 수 없는 경우가 있기 때문에 SocketException을 throw 해 주어야 합니다.

 

DatagramSocket의 주요 메소드는 send(DatagramPacket p) , receive(DatagramPacket p), setSoTimeout(int timeout), close() 가 있습니다.

 

사용의 예는 예제를 보면서 확인하도록 하겠습니다.

 

 

Java UDP Client Example

 

인터넷 표준 인 QOTD 서비스를 구현 한 서버에서 인용 부호를 요청하는 프로그램 코드의 예제입니다.

 

QOTD서비스에서는 서버에 접속만 하면 되고, Client가 서버로 메시지를 보내지 않기 때문에 버퍼의 데이터가 존재 하지 않습니다. 아래 코드에서 확인 해 보도록 하곘습니다.

package com.woolbro.udpExample;

import java.io.*;
import java.net.*;
 
public class QuoteClient {
 
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Syntax: QuoteClient <hostname> <port>");
            return;
        }
 
        String hostname = args[0];
        int port = Integer.parseInt(args[1]);
 
        try {
            InetAddress address = InetAddress.getByName(hostname);
            DatagramSocket socket = new DatagramSocket();
 
            while (true) {
 
                DatagramPacket request = new DatagramPacket(new byte[1], 1, address, port);
                socket.send(request);
 
                byte[] buffer = new byte[512];
                DatagramPacket response = new DatagramPacket(buffer, buffer.length);
                socket.receive(response);
 
                String quote = new String(buffer, 0, response.getLength());
 
                System.out.println(quote);
                System.out.println();
 
                Thread.sleep(10000);
            }
 
        } catch (SocketTimeoutException ex) {
            System.out.println("Timeout error: " + ex.getMessage());
            ex.printStackTrace();
        } catch (IOException ex) {
            System.out.println("Client error: " + ex.getMessage());
            ex.printStackTrace();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

클라이언트 프로그램을 실행 하려면, 이클립스의 Run Configure 에서 변수에 djxmmx.net 17 을 넣어주거나

명령프롬포트에서

java QuoteClient djxmmx.net 17

라고 명령 해 줍니다.

 

실행 되는 동안 작성한 클라이언트는 서버로부터 메시지를 계속 받습니다.

"Oh the nerves, the nerves; the mysteries of this machine called man! Oh the little that unhinges it, poor creatures that we are!" Charles Dickens (1812-70) "Oh the nerves, the nerves; the mysteries of this machine called man! Oh the little that unhinges it, poor creatures that we are!" Charles Dickens (1812-70)

위의 글처럼, 서버에서 받은 데이터를 출력 해 줍니다.

 

 

Java UDP Server Example

위의 클라이언트(Java UDP Client Example)에 대해 서버를 구현 해 보도록 하겠습니다.

 

연결 된 포트는 17번이었기 때문에 포트 17에서 수신 대기하고 클라이언트의 요청을 기다리는 UDP 서버입니다.

 

 

package com.woolbro.udpExample;

import java.io.*;
import java.net.*;
import java.util.*;
 
public class QuoteServer {
    private DatagramSocket socket;
    private List<String> listQuotes = new ArrayList<String>();
    private Random random;
 
    public QuoteServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
        random = new Random();
    }
 
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Syntax: QuoteServer <file> <port>");
            return;
        }
 
        String quoteFile = args[0];
        int port = Integer.parseInt(args[1]);
 
        try {
            QuoteServer server = new QuoteServer(port);
            server.loadQuotesFromFile(quoteFile);
            server.service();
        } catch (SocketException ex) {
            System.out.println("Socket error: " + ex.getMessage());
        } catch (IOException ex) {
            System.out.println("I/O error: " + ex.getMessage());
        }
    }
 
    private void service() throws IOException {
        while (true) {
            DatagramPacket request = new DatagramPacket(new byte[1], 1);
            socket.receive(request);
 
            String quote = getRandomQuote();
            byte[] buffer = quote.getBytes();
 
            InetAddress clientAddress = request.getAddress();
            int clientPort = request.getPort();
 
            DatagramPacket response = new DatagramPacket(buffer, buffer.length, clientAddress, clientPort);
            socket.send(response);
        }
    }
 
    private void loadQuotesFromFile(String quoteFile) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(quoteFile));
        String aQuote;
 
        while ((aQuote = reader.readLine()) != null) {
            listQuotes.add(aQuote);
        }
 
        reader.close();
    }
 
    private String getRandomQuote() {
        int randomIndex = random.nextInt(listQuotes.size());
        String randomQuote = listQuotes.get(randomIndex);
        return randomQuote;
    }
}

 

따로 준비 해야 할 것은, test.txt 파일입니다. 파일을 읽어와서 해당 파일을 서버 -> 클라이언트 로 전송 할 것이기 때문에 test.txt파일을 만들고 아래 내용을 넣어 줍니다.

 

<test.txt>
Whether you think you can or you think you can't, you're right - Henry Ford There are no traffic jams along the extra mile - Roger Staubach Build your own dreams, or someone else will hire you to build theirs - Farrah Gray What you do today can improve all your tomorrows - Ralph Marston Remember that not getting what you want is sometimes a wonderful stroke of luck - Dalai Lama

 

test.txt 파일은 자바 프로젝트를 만든 경로에 위치하게 해 주면, 프로그램 실행 시에 다른 매개변수를 넣지 않아도 찾아 읽어 오게 됩니다.

 

위의 서버 프로그램을 이클립스에서 Run Configuration 로 들어가 arguments를 test.txt 17 로 넣어주거나 , 명령 프롬프트 창에서 다음과 같이 입력합니다.

java QuoteServer test.txt 17

 

그리고, 위에서 만들었던 QuoteClient의 Run Configuration Arguments를 수정 해 줍니다. 이전에 설정 되어 있었던 설정은 다음과 같습니다.

 

java QuoteClient djxmmx.net 17

위의 djxmmx.net의 부분을 localhost로 바꾸어줍니다.

 

서버를 실행 후, 클라이언트를 실행 하게 되면 방금 작성했던 QuoteServer과 QuoteClient가 17번 포트를 통해 test.txt 안에 있는 내용을 전송합니다.

 

 

이상 UDP Server, Client의 간단한 프로그래밍 예제였습니다.