반응형

원본 - http://rahxephon.tistory.com/878


16.4 URLConnection 클래스

 

URLConnection 클래스는 Application과 URL간의 통신링크를 위한 작업을 수행합니다. 네트웍의 일반적인 작업들은 먼저 Connection 연결을 한 후, 그 Connection에 연결되어 있는 스트림을 생성합니다.

 

URL클래스는 URLConnection클래스의 기능을 내부적으로 수행하고 있습니다. 앞 절의 URL클래스 예제에서 여러분은 URLConnection없이 Connection을 자동으로 열고 스트림을 생성하는 것을 보았을 것입니다. 즉, 이것은 URL클래스가 URLConnection의 작업을 내부적으로 처리한다고 볼 수 있습니다.

 

다음 예제들은 특정 URL로부터 데이터를 읽어 콘솔에 출력하는 프로그램입니다. URL클래스와 URLConnection클래스의 관계를 생각하여 따로 작성한 것입니다. 이 예제 둘을 잘 비교하시면 URL클래스와 URLConnection클래스와의 관계를 이해 하실 수 있을 것입니다.

 

URLRead.java(URL클래스로 스트림 받기)

import java.net.*;

import java.io.*;

public class URLRead {

   public static void main(String[] args) throws Exception {

       URL ocu = new URL("http://www.jabook.org/");

       BufferedReader in = new BufferedReader(new InputStreamReader(ocu.openStream()));

       String inputLine;        

       while ((inputLine = in.readLine()) != null)

          System.out.println(inputLine);

       in.close();    

   }

}

C:\JavaExample\16>javac URLRead.java

C:\JavaExample\16>java URLRead

<html>

<head>

<title>보석자바</title>

</head>

    <frameset rows="42,100%" frameborder=0 border=0>

    <frame src="head.html" name="menuhead" scrolling="no" marginwidth="0

" marginheight="0" target="_self" noresize>

      <frame name="down" src="intro.html" scrolling="auto">

    </frameset>

</html>

 

URLConnectionRead.java(URLConnection이용하기)

import java.net.*;

import java.io.*;

public class URLConnectionRead {

   public static void main(String[] args) throws Exception {

       URL ocu = new URL("http://www.jabook.org/");

       URLConnection con = ocu.openConnection();

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

       String inputLine;

       while ((inputLine = in.readLine()) != null)

       System.out.println(inputLine);

       in.close();    

   }

}

C:\JavaExample\16>javac URLConnectionRead.java

C:\JavaExample\16>java URLConnectionRead

<html>

<head>

<title>보석자바</title>

</head>

    <frameset rows="42,100%" frameborder=0 border=0>

    <frame src="head.html" name="menuhead" scrolling="no" marginwidth="0

" marginheight="0" target="_self" noresize>

      <frame name="down" src="intro.html" scrolling="auto">

    </frameset>

</html>

 

URLRead.java 예제는 URL클래스에서 이미 논의한 바 있기 때문에 쉽게 이해 하실 수 있을 것입니다. 문제는 URLConnectionRead.java의 URLConnection부분입니다. 실제로는 URLConnection을 사용하여 Connection설정부터 하는 것이 정석입니다. 하지만, 지름길이라는 것도 있지 않겠습니까? 쉽게 생각 해서 URLRead.java 예제가 지름길이라면 URLConnectionRead.java 예제는 정석이라고 보시면 편하실 겁니다.

 

그럼 먼저 URL클래스에서 URLConnection클래스를 사용하는 방법에 대해 알아보도록 하겠습니다. 그 과정을 보면 다음과 같습니다.

 

n        URL ocu = new URL("http://www.jabook.org/"); à URL클래스 생성

n        URLConnection con = ocu.openConnection(); à URL클래스에서 Connection설정

n        con.getInputStream() à URLConnection클래스에서 입력스트림설정

 

지정된 URL로 URL클래스 객체를 생성하고, openConnection()메서드를 통해 URLConnection의 접속객체를 생성하여 주어진 URL에 접속 하고 있습니다. 그리고 나서 URLConnection 객체로부터 InputStream을 구하고, 이를 문자 데이터를 읽기에 편리한 InputStreamReader로 쌉니다. 다시 이를 효과적으로 읽기 위해 버퍼화된 입력스트림 BufferedReader로 싸서 최종적인 입력스트림을 만들어 주었습니다.

 

그 이외의 작업들은 URL클래스와 동일합니다. 우리는 URL클래스에서 쉽게 위의 아랫부분 두 줄을 다음과 같이 사용할 수도 있습니다.

 

n        ocu.openStream();

 

이제 이 절의 서두에서 설명한 ‘URL클래스가 URLConnection의 작업을 내부적으로 처리한다’는 말을 이해 하시겠습니까? 이 말은 즉, URL클래스의 openStream()메서드 내부에서 URLConnection작업이 이루진다고 보시면 될 것입니다.

 

지금까지 우리는 URLConnection 객체를 통해 URL 객체가 참조하는 자원에 대해 읽어 오는 것들만 봐 왔습니다. 하지만 이 URLConnection 객체는 URL 객체를 읽기 뿐 아니라 쓰기도 합니다. 이를 자바 튜터리얼(The JavaTM Tutorial)을 참조하면서 설명을 해보도록 하겠습니다.

 

사실 URL 자원은 서버측에 있고, 이에 접근하고자 하는 URL 애플리케이션은 클라이언트 측 프로그램입니다. URL에 데이터 쓴다는 것은 클라이언트가 서버에 서비스를 요청하기 위해 보내는 질의(query)입니다. 이러한 질의는 보통 html form을 통해 이루어지고, 서버는 이 질의를 받아 그에 따른 처리를 하여 클라이언트에 응답합니다. 그러면 클라이언트는 서버로부터 받은 응답을 읽어 출력합니다.

 

우리는 여기서 서버측 프로그램을 작성하지는 않고 다만 응답을 할 수 있는 cgi 스크립트 자원을 URL로 하여 이에 질의를 보내고, 거기서 온 응답을 DOS 창에서 시스템 출력하고자 합니다. 우리가 접근할 cgi 자원은 ‘http://java.sun.com/cgi-bin/backwards’ 입니다. 이는 클라이언트가 보낸 스트링을 그 순서를 뒤집어 되보내는 pearl로 작성한 cgi 스크립트입니다.

 

가령 DOS 창의 명령행을 통해 명령행 인자로 "java"를 사용해 프로그램을 실행하면, 서버측의 cgi 스크립트 backwards 가 이 "java"를 문자 순서를 뒤집은 "avaj"를 클라이언트에 전달하고, 클라이언트(우리의 시험 프로그램)은 그 결과를 시스템 출력하도록 하는 것 우리 시험 프로그램의 목적입니다. 이해하기 힘드시죠? 다음 예제를 보면서 설명을 해 보겠습니다.

 

URLConnectionRead.java(URLConnection이용하기)

import java.io.*;

import java.net.*;

public class Reverse {

    public static void main(String[] args) throws Exception {

        if (args.length != 1) {

            System.err.println("다음 형식으로 입력하세요.");

            System.err.println("java Reverse \"string\"");

            System.exit(1);

        }

        String stringToReverse = URLEncoder.encode(args[0]);

        URL url = new URL("http://java.sun.com/cgi-bin/backwards");

        URLConnection connection = url.openConnection();

        connection.setDoOutput(true);

        PrintWriter out = new PrintWriter(connection.getOutputStream());

        out.println("string=" + stringToReverse);

        out.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

        String inputLine;

        while ((inputLine = in.readLine()) != null)

            System.out.println(inputLine);

        in.close();

    }

}

C:\JavaExample\16>javac Reverse.java

C:\JavaExample\16>java Reverse www.jabook.org

www.jabook.org

 reversed is:

gro.koobaj.www

 

프로그램을 실행하기 위해서는 실행 문 마지막에 출력할 문자를 넣어줘야 합니다 안 그러면 서버측에서 아무런 대답을 할 수가 없겠죠. 명령행인자의 배열 길이가 1이 아니면, 즉, 명령행인자가 없거나 2개 이상이면 오류 메시지를 출력하고 프로그램을 마칩니다.

 

n        if (args.length != 1) {

n           System.err.println("다음 형식으로 입력하세요.");

n           System.err.println("java Reverse \"string\"");

n           System.exit(1);

n        }

 

도스 명령을 정확히 입력하였으면, 명령행인자 args[0]를 읽어 String형 변수 stringToReverse에 저장합니다. 여기서 처음 본 클래스가 나타났죠? 이 URLEncoder클래스는 전달 받은 String을 x-www-form-urlencoded 형식의 MIME 유형에 맞도록 변환시킵니다. 자세한 것은 다음 절에서 다루기로 하겠습니다.

 

n        String stringToReverse = URLEncoder.encode(args[0]);

 

URL객체를 생성하여 주어진 URL에 접속을 합니다.

 

n        URL url = new URL("http://java.sun.com/cgi-bin/backwards");

n        URLConnection c = url.openConnection();

 

여기서 URL 접속 객체 c를 URLConnection 개체에 쓰기 가능하도록 지정합니다. setDoOutput()메서드의 디폴트 값은 false이므로, true로 지정하지 않으면 쓰기가 불가능합니다.

 

n        c.setDoOutput(true);

 

현재 열려있는 URLConnection을 통해 데이터를 쓰는 출력스트림 PrintWriter를 열어  이를 통해 서버측에 질의를 합니다.

 

n        PrintWriter out = new PrintWriter(c.getOutputStream());

n        out.println("string=" + stringToReverse);

 

출력스트림을 닫습니다.

 

n        out.close();

 

그 뒤에 오는 소스들은 이미 설명하였으니 따로 설명하지 않겠습니다. 당연 URL에 접속을 했으니 주어진 정보들을 읽어 들이겠죠?

 

URLConnection클래스의 생성자메서드

protected URLConnection(URL url) : 지정된 URL로의 URL 연결을 구성한다. URL에 의해 참조되는 객체로의 연결이 작성되지 않는다.

 

URLConnection클래스의 주요 멤버메서드

public abstract void connect() throws IOException : 아직 접속이 이루어지지 않은 경우 현재 URL 이 참조하는 자원에 대한 통신 링크를 연다. 이미 접속이 이루어진 경우는 별 다른 조처를 취하지 않는다. 이 메서드는 추상 메서드이므로 각 프로토콜에 따른 URLConnection 부분 클래스에서 구체적인 접속 방법이 정의되어야 한다.

public void setDoInput(boolean doinput) : URLConnection에 대한 doInput 필드값을 지정된 값으로 설정한다. URL 연결은 입출력에 사용될 수 있다. URL 연결을 입력용으로 사용하려는 경우 DoInput 플래그를 true로 설정하고, 그렇지 않은 경우는 false로 설정해야 한다. 기본값은 DoOutput이 명시적으로 true로 설정되지 않은 경우 true이며, 이때 DoInput의 기본값은 false이다.

public InputStream getInputStream() throws IOException : 열린 연결에서 읽은 입력 스트림을 리턴한다.

public void setDoOutput(boolean dooutput) : URLConnection에 대한 doOutput 필드값을 지정된 값으로 설정한다. URL 연결은 입출력에 사용될 수 있다. URL 연결을 출력용으로 사용하려는 경우 DoOutput 플래그를 true로 설정하고, 그렇지 않은 경우는 false로 설정해야 한다. 기본값은 false이다.

public OutputStream getOutputStream() throws IOException : 연결에 기록한 출력 스트림을 리턴한다.

public String getHeaderField(int n) : n번째 헤더 필드의 값을 되돌린다. 만약 이 헤더에 n보다 적은 필드가 있으면 null을 되돌린다.

public Object getContent() throws IOException : 현재 URLConnection의 컨텐츠를 검색하여 그 결과를 되돌린다. 이 때 먼저 getContentType()메서드를 호출해 현재 URLConnection의 컨텐트 유형을 결정하는데, 만약 이 컨텐트 유형이 이미 알고 있는 것이 아니고 처음 보는 것이라면 다음 과정을 통해 이 유형에 대한 컨텐트 헨들러content handler가 생성된다. 

1. 만약 애플리케이션이 setContentHandlerFactory()메서드를 이용해 컨텐트 헨들러 공장 인스턴스를 설치했다면, 이 인스턴스의 createContentHandler()메서드가 그 컨텐트 유형을 인자로 하여 호출된다. 그러면 그 컨텐트 유형에 맞는 컨텐트 헨들러가 되돌려진다. 

2. 만약 아직 컨텐트 헨들러 공장 인스턴스가 설치되지 않았거나 createContentHandler()메서드가 null을 되돌리면, 그 애플리케이션은 다음과 같은 명칭의 클래스를 탑재한다. 

‘sun.net.www.content.<contentType>’ 여기서 <contentType>는 컨텐트 유형을 나타내는 스트링으로, 이 스트링 중에 모든 슬래시 '/'는 마침표 '.'로, 알파뉴메릭 문자(영문자 알파벳 및 숫자)가 아닌 것은 밑줄 '_'로 대치된다. 

3. 만약 지정한 클래스가 존재하지 않거나, 있더라도 그것이 ContentHandler의 부분클래스가 아니면, UnknownServiceException가 던져진다.

 

그럼 ‘왜 URLConnection 클래스가 존재하며, 어떤 용도로 사용하는 것일까?’ 하는 의문이 생기지 않습니까? 다행히도 get방식의 데이터를 전송할 경우 URL에 첨부시키면 되지만 Post방식일 때는 어떻게 할까요? 바로 문제는 여기에 있습니다. 여러분이 Post방식으로 데이터를 먼저 보내고 그 결과를 받기 위해서는 URLConnection클래스를 이용해서 이 문제를 해결할 수 있습니다.  즉, 이것은 HTTP의 송신 명령인 POST와 같은 기능을 실행할 때 사용한다고 보면 편할 것입니다. 이것에 관련된 예제는 URLEncdoer와 URLDecoder절을 참고하시기 바랍니다.

 

☞ URLConnection클래스

Application과 URL간의 통신링크를 위한 작업을 수행한다.


반응형

WRITTEN BY
데르벨준

,