libcurlÀ» ÀÌ¿ëÇÑ °£´ÜÇÑ Web ÇÁ·Î±×·¡¹Ö
ÃÑ ÆäÀÌÁö ¼ö : 3224

Àüü ÇÔ¼ö/¿ë¾î»çÀü
Facebook Joinc ±×·ì   Joinc QA »çÀÌÆ®



joinc´Â Firefox¿Í chrome¿¡¼­ Å×½ºÆ® Çß½À´Ï´Ù. IE¿¡¼­´Â Å×À̺íÀÌ ±úÁö°Å³ª À̹ÌÁö°¡ º¸ÀÌÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ƯÈ÷ ±¸±Û DocsÀ̹ÌÁöÀÇ °æ¿ì ¿¢¹Úó¸®µÉ ¼ö ÀÖ½À´Ï´Ù.

¿ø¹® : http://www.linuxdevcenter.com/pub/a/linux/2005/05/05/libcurl.html?page=1

Contents

1 Curl¿¡ ´ëÇØ¼­
2 Curl »ç¿ë ±âÃÊ
3 HTTP GET:À¥ ÆäÀÌÁö ±Ü¾î¿À±â
4 FTP Download: FTP µ¥ÀÌÅÍ ´Ù¿î·Îµå
5 FTP ¾÷·Îµå
6 HTTP POST

1 Curl¿¡ ´ëÇØ¼­

curlÀº µ¥ÀÌÅÍ Àü¼Û°ú °ü·ÃµÈ ÇÁ·Î±×·¥ÀÇ ºü¸¥ ÀÛ¼ºÀ» À§Çؼ­ »ç¿ëÇÏ´Â command line toolÀÌ´Ù. HTTP, FTP, LDAP, TELNET, HTTPS, DICT¿Í °°Àº ÇÁ·ÎÅäÄÝÀ» Áö¿øÇϸç, SSLÀ» °¡Áö´Â °¢°¢ÀÇ ÇÁ·ÎÅäÄÝ ¿ª½Ã Áö¿øÇÑ´Ù. ¶ÇÇÑ HTTP±â¹ÝÀÇ upload, proxies, cookies, user+password ÀÎÁõÀ» »ç¿ëÇÒ ¼öµµ ÀÖ´Ù.

ÀÌ·¯ÇÑ ÅøÀÇ Á¦°ø°ú´Â º°µµ·Î À§ÀÇ ÇÁ·ÎÅäÄݵéÀ» Áö¿øÇϴ Ŭ¶óÀ̾ðÆ®ÀÇ Á¦ÀÛÀ» µµ¿ÍÁÖ±â À§ÇÑ libCURLÀ» Á¦°øÇÑ´Ù. libCURLÀ» ÀÌ¿ëÇÏ¸é µ¥ÀÌÅÍ Àü¼Û°ú °ü·ÃµÈ ÇÁ·Î±×·¥À» ºü¸£°Ô ÀÛ¼ºÇÒ ¼ö ÀÖ´Ù.

ÀÌ ¹®¼­´Â libCURLÀÇ API¸¦ ÀÌ¿ëÇØ¼­ ÇÊ¿äÇÑ µ¥ÀÌÅÍÀü¼Û ÇÁ·Î±×·¥À» ¸¸µå´Â ¹ý¿¡ ´ëÇØ¼­ ¼³¸íÀ» ÇÒ °ÍÀÌ´Ù. ½¬¿î ¼³¸íÀ» À§Çؼ­ ´ÙÀ½°ú °°Àº ¿¹Á¦¸¦ ÀÛ¼ºÇÏ°Ô µÉ °ÍÀÌ´Ù.
  • HTTP GET : URL·Î ºÎÅÍ ³»¿ëÀ» °¡Á®¿Â´Ù.
  • Anonymous FTP ´Ù¿î·Îµå : FTP¼­¹ö¿¡ Á¢¼ÓÇØ¼­ ÆÄÀÏÀ» °¡Á®¿Â´Ù.
  • HTTP POST: Web FormÀ» Èä³»³»¾î¼­ µ¥ÀÌÅ͸¦ Àü¼ÛÇÑ´Ù.
  • Authenticated FTP Upload : ID+Password·Î Á¢¼ÓÇØ¼­ ÆÄÀÏÀ» UploadÇÑ´Ù.

libCURLÀº C ¶óÀ̺귯¸®ÀÌ´Ù. ¸î¸î ¿¹Á¦´Â ºü¸¥ÀÛ¼ºÀ» À§Çؼ­ C++À» ÀÌ¿ëÇÒ°ÍÀ̱ä ÇÏÁö¸¸, ÀÌÇØÇÏ°í »ç¿ëÇϴµ¥ ¹«¸®´Â ¾øÀ» °ÍÀÌ´Ù - C++ÀÇ ÅÛÇø´Àº ÇÁ·Î±×·¥ ÀÛ¼º¿¡ °É¸®´Â ½Ã°£À» ´ëÆø ÁÙ¿äÁØ´Ù. Å×½ºÆ® ÇÁ·Î±×·¥À» ¸¸µé°íÀÚ ÇÒ¶§ ½Ã°£À» Àý¾àÇϵµ·Ï ÇØ ÁØ´Ù -.

¿¹Á¦´Â Ubuntu ȯ°æ¿¡¼­ Å×½ºÆ®µÇ¾ú´Ù. libCURLÀÇ ¹öÁ¯Àº 7.12.3À» »ç¿ëÇÒ °ÍÀÌ´Ù. ¹öÁ¯ÀÌ ´Þ¶óµµ Å« ¹®Á¦´Â ¾øÀ» °ÍÀ̶ó »ý°¢µÈ´Ù.

2 Curl »ç¿ë ±âÃÊ

CurlÀ» »ç¿ëÇϱâ Àü¿¡ client/server ¿¡¼­ÀÇ ¿äû°ú ÀÀ´ä°úÁ¤ÀÌ ¾î¶»°Ô ÀÌ·ç¾îÁö´ÂÁö ¾Ë¾Æº¸µµ·Ï ÇÏÀÚ. HTTP ÇÁ·ÎÅäÄÝÀ» ÀÌ¿ëÇØ¼­ ¼³¸íÇϵµ·Ï ÇϰڴÙ.
  1. clinet´Â server·Î ¿¬°áÀ» ½ÃµµÇÑ´Ù.
  2. ¿¬°áÀÌ µÇ¾ú´Ù¸é client´Â GET, POST¸¦ ÀÌ¿ëÇØ¼­ µ¥ÀÌÅ͸¦ º¸³¾ °ÍÀÌ´Ù.
  3. server´Â ¿äûÀ» ¹Þ°í ¿äû¿¡ ´ëÇÑ ÀÀ´äÀ» º¸³½´Ù.(HTMLÆäÀÌÁö ȤÀº ¿¡·¯ ¸Þ½ÃÁö)
  4. client´Â server·ÎÀÇ ¿¬°áÀ» Á¾·áÇÑ´Ù.
    <!> Á»´õ ÀÚ¼¼ÇÑ ³»¿ëÀº TCP/IP¹®¼­¸¦ Âü°íÇϱ⠹ٶõ´Ù.

libCURLÀº ÀÌ·¯ÇÑ ÇÁ·Î¼¼½ºÀÇ Áß°£¿¡¼­ Á߰迪ÇÒÀ» ÇÑ´Ù. »ç¿ëÀº context °´Ã¼¿Í ¿äûµ¥ÀÌÅÍ (URL, ÀÎÀÚ)¿Í Äݹé(callback functions)Çü½ÄÀÇ response handler¸¦ Á¤ÀÇÇØ ÁÖ¸éµÈ´Ù. ÀÌ °´Ã¤¸¦ ¶óÀ̺귯¸®¿¡ ³Ñ±â°Ô µÇ¸é, ¶óÀ̺귯¸®´Â Àú¼öÁØ¿¡¼­ ÀϾ´Â ³×Æ®¿öÅ© Åë½ÅÀ» ¾Ë¾Æ¼­ ÇÚµéÇÏ°í ±× °á°ú °ªÀ» response handler¸¦ ÅëÇØ¼­ ³Ñ°ÜÁÖ°Ô µÈ´Ù.

libCURLÀº °í¼öÁØÀÇ ¶óÀ̺귯¸®·Î ÇÁ·Î±×·¡¸Ó´Â ÇÁ·ÎÅäÄÝÀÌ ¾î¶»°Ô »ý°Ü¸Ô¾ú´ÂÁö¿¡ ´ëÇØ¼­ ½Å°æ¾µ ÇÊ¿ä ¾øÀÌ, µ¥ÀÌÅ͸¸ ³Ñ°ÜÁÖ´Â Á¤µµ·Î ÇÊ¿äÇÑ ÇÁ·Î±×·¥À» ÀÛ¼ºÇÒ¼ö ÀÖ´Ù. libCURLÀÌ Application °èÃþ¾Æ·¡¸¦ ¿ÏÀüÈ÷ Ãß»óÈ­ ½ÃÄÑÁֱ⠶§¹®ÀÌ´Ù.

libCURLÀº ¾Æ·¡¿Í °°Àº easy¶ó´Â À̸§À» °¡Áö´Â ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇÑ´Ù.
  1. curl_blogal_init : curl ¶óÀ̺귯¸®¸¦ ÃʱâÈ­ ÇÑ´Ù.
  2. curl_easy_init : context¸¦ »ý¼ºÇÑ´Ù.
  3. curl_easy_setopt : context ¼³Á¤
  4. curl_easy_perform : ¿äûÀ» ÃʱâÈ­ Çϰí callbackÇÔ¼ö¸¦ ´ë±â½ÃŲ´Ù.
  5. curl_easy_cleanup : context¸¦ ¾ø¾Ø´Ù.
  6. curl_global_cleanup : curl ¶óÀ̺귯¸®¸¦ ¾ø¾Ø´Ù.

curl_easy_setopt ÇÔ¼ö´Â ´ÙÀ½°ú °°ÀÌ ¼±¾ðµÇ¾î ÀÖ´Ù.
curl_easy_setopt(CURL *ctx, CURLoption key, value) 
 

3 HTTP GET:À¥ ÆäÀÌÁö ±Ü¾î¿À±â

ÀÌÁ¦ ÇÁ·Î±×·¥À» ¸¸µé¾îº¸µµ·Ï ÇÏÀÚ. ÀÌ ÇÁ·Î±×·¥Àº HTTP GETÀ» ÀÌ¿ëÇØ¼­ À¥ÆäÀÌÁö¸¦ ±Ü¾î¿À´Â ÀÏÀ» ÇÑ´Ù. Çì´õ´Â Ç¥ÁØ¿¡·¯·Î body ºÎºÐÀº Ç¥ÁØÃâ·ÂÇü½ÄÀ¸·Î °¡Á®¿Àµµ·Ï ÇϰڴÙ.

curl_easy_init ÇÔ¼ö¸¦ È£ÃâÇØ¼­ context °´Ã¼¸¦ »ý¼ºÇÑ´Ù.
CURL *ctx = curl_easy_init (); 
 
curl_easy_setopt ¸¦ ÀÌ¿ëÇØ¼­ context°´Ã¼¸¦ ¼³Á¤ÇÑ´Ù. CURLOPT_URLÀº ¸ñÇ¥ URLÀÌ´Ù.
curl_easy_setopt(ctx, CURLOPT_URL, argv[1]); 
 
curl_easy_setopt¸¦ ÀÌ¿ëÇϸé À̿ܿ¡µµ ¸î °¡Áö ¼³Á¤À» ´õ ÇØÁÙ ¼ö ÀÖ´Ù.
curl_easy_setiopt(ctx, CURLOPT_WRITEHEADER, stderr); 
curl_easy_setiopt(ctx, CURLOPT_WRITEDATA, stdout); 
 
header Á¤º¸´Â Ç¥ÁØ¿¡·¯·Î, bodyÁ¤º¸´Â Ç¥ÁØÃâ·ÂÀ¸·Î °¡Á®¿Àµµ·Ï ¼³Á¤À» Çß´Ù.

ÀÌÁ¦ curl_easy_performÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ½ÇÁ¦ ÆäÀÌÁö¸¦ ±Ü¾î¿À´Â ÀÏÀ» Çϵµ·Ï ÇÏÀÚ.
const CURLcode rc = curl_easy_perform(ctx); 
if (CURLE_OK != rc) 
{ 
    std::cerr << "Error from cURL: " << curl_easy_strerror(rc) std::endl; 
} 
else 
{ 
    // µ¥ÀÌÅÍ Ã³¸® 
} 
 

ÀÌÈÄ µ¥ÀÌÅÍ´Â ¾Æ·¡¿Í °°ÀÌ curl_easy_getinfo¸¦ ÅëÇØ¼­ ¾ò¾î¿Í¼­ ó¸®ÇÏ¸é µÈ´Ù.
long statLong; 
curl_easy_getinfo(ctx, CURLINFO_HTTP_CODE, &statLong); 
std::cout << "HTTP response code: " << statLong << std::endl; 
 
¿øÇÏ´Â °ªÀ» °¡Á®¿À±â À§Çؼ­´Â µ¥ÀÌÅÍÀÇ Å¸ÀÔ¿¡ ¸Â´Â ÀÎÀÚ¸¦ ½á¾ß ÇÑ´Ù. 200À̳ª 404¿Í °°Àº HTTP ÀÀ´äÄڵ带 °¡Á®¿À±æ ¿øÇÑ´Ù¸é CURLINFO_HTTP_CODE¸¦ Àü¼Û¹ÞÀº ¹®¼­ÀÇ Å©±â¸¦ ¾Ë¾Æ³»±æ ¿øÇÑ´Ù¸é CURLINFO_SIZE_DOWNLOAD¸¦ »ç¿ëÇÏ´Â ½ÄÀÌ´Ù.

¸ðµç ÀÛ¾÷ÀÌ ´Ù ³¡³µ´Ù¸é, curl_easy_cleanupÀ» È£ÃâÇØ¼­ curl_easy_setopt °´Ã¼¸¦ ¼Ò¸ê½ÃÄÑ¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ»°æ¿ì ¸Þ¸ð¸®´©¼ö Çö»óÀ» °Þ°Ô µÉ °ÍÀÌ´Ù.
/* 
sample for O'ReillyNet article on libcURL: 
    {TITLE} 
    {URL} 
    AUTHOR: Ethan McCallum 
 
Scenario: use http/GET to fetch a webpage 
 
ÀÌ ÄÚµå´Â Ubuntu ¸®´ª½º Kernel 2.6.15¿¡¼­  
libcURL ¹öÁ¯ 7.15.1·Î Å×½ºÆ® µÇ¾ú´Ù. 
2006³â 8¿ù 3ÀÏ 
*/ 
 
#include<iostream> 
 
extern "C" { 
    #include<curl/curl.h> 
} 
 
// - - - - - - - - - - - - - - - - - - - - 
 
enum { 
    ERROR_ARGS = 1 , 
    ERROR_CURL_INIT = 2 
} ; 
 
enum { 
    OPTION_FALSE = 0 , 
    OPTION_TRUE = 1 
} ; 
 
enum { 
    FLAG_DEFAULT = 0  
} ; 
 
// - - - - - - - - - - - - - - - - - - - - 
 
int main( const int argc , const char** argv ){ 
 
    if( argc != 2 ){ 
        std::cerr << " Usage: ./" << argv[0] << " {url} [debug]" << std::endl ; 
        return( ERROR_ARGS ) ; 
    } 
 
    const char* url = argv[1] ; 
 
    // lubcURL ÃʱâÈ­  
    curl_global_init( CURL_GLOBAL_ALL ) ; 
 
    // context°´Ã¼ÀÇ »ý¼º 
    CURL* ctx = curl_easy_init() ; 
 
    if( NULL == ctx ){ 
        std::cerr << "Unable to initialize cURL interface" << std::endl ; 
        return( ERROR_CURL_INIT ) ; 
    } 
 
    // context °´Ã¼¸¦ ¼³Á¤ÇÑ´Ù.     
    // ±Ü¾î¿Ã urlÀ» ¸í½ÃÇϰí, urlÀÌ URLÁ¤º¸ÀÓÀ» ¾Ë·ÁÁØ´Ù. 
    curl_easy_setopt( ctx , CURLOPT_URL,  url ) ; 
 
    // no progress bar: 
    curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , OPTION_TRUE ) ; 
 
    /* 
    By default, headers are stripped from the output. 
    They can be: 
 
    - passed through a separate FILE* (CURLOPT_WRITEHEADER) 
 
    - included in the body's output (CURLOPT_HEADER -> nonzero value) 
        (here, the headers will be passed to whatever function 
         processes the body, along w/ the body) 
 
    - handled with separate callbacks (CURLOPT_HEADERFUNCTION) 
        (in this case, set CURLOPT_WRITEHEADER to a 
         matching struct for the function) 
 
    */ 
     
    // Çì´õ´Â Ç¥ÁØ¿¡·¯·Î Ãâ·ÂÇϵµ·Ï ÇÏ´Ù.  
    curl_easy_setopt( ctx , CURLOPT_WRITEHEADER , stderr ) ; 
 
 
    // body µ¥ÀÌÅʹ ǥÁØÃâ·Â Çϵµ·Ï ÇÑ´Ù. 
    curl_easy_setopt( ctx , CURLOPT_WRITEDATA , stdout ) ; 
 
    // context °´Ã¼ÀÇ ¼³Á¤ Á¾·á  
 
 
    // À¥ÆäÀÌÁö¸¦ ±Ü¾î¿Â´Ù.  
 
    const CURLcode rc = curl_easy_perform( ctx ) ; 
 
    if( CURLE_OK != rc ){ 
 
        std::cerr << "Error from cURL: " << curl_easy_strerror( rc ) << std::endl ; 
 
    }else{ 
 
        // get some info about the xfer: 
        double statDouble ; 
        long statLong ; 
        char* statString = NULL ; 
 
        // HTTP ÀÀ´äÄڵ带 ¾ò¾î¿Â´Ù.  
        if( CURLE_OK == curl_easy_getinfo( ctx , CURLINFO_HTTP_CODE , &statLong ) ){ 
            std::cout << "Response code:  " << statLong << std::endl ; 
        } 
 
        // Content-Type ¸¦ ¾ò¾î¿Â´Ù. 
        if( CURLE_OK == curl_easy_getinfo( ctx , CURLINFO_CONTENT_TYPE , &statString ) ){ 
            std::cout << "Content type:   " << statString << std::endl ; 
        } 
 
        // ´Ù¿î·ÎµåÇÑ ¹®¼­ÀÇ Å©±â¸¦ ¾ò¾î¿Â´Ù. 
        if( CURLE_OK == curl_easy_getinfo( ctx , CURLINFO_SIZE_DOWNLOAD , &statDouble ) ){ 
            std::cout << "Download size:  " << statDouble << "bytes" << std::endl ; 
        } 
 
        //  
        if( CURLE_OK == curl_easy_getinfo( ctx , CURLINFO_SPEED_DOWNLOAD , &statDouble ) ){ 
            std::cout << "Download speed: " << statDouble << "bytes/sec" << std::endl ; 
        } 
 
    } 
 
    // cleanup 
    curl_easy_cleanup( ctx ) ; 
    curl_global_cleanup() ; 
 
    return( 0 ) ; 
 
} // main() 
 

4 FTP Download: FTP µ¥ÀÌÅÍ ´Ù¿î·Îµå

ÇöÀç´Â À¥¼­ºñ½º¸¦ ÅëÇØ¼­ µ¥ÀÌÅ͸¦ ¾ò´Â °æ¿ì°¡ ¾ÐµµÀûÀÌÁö¸¸, ¿©ÀüÈ÷ FTP´Â µ¥ÀÌÅÍÀÇ Àü¼ÛÀ» À§ÇÑ ¿ëµµ·Î ³Î¸® »ç¿ëµÇ°í ÀÖ´Ù.

FTP´Â scriptÀÇ ÀÛ¼ºÀ» ÅëÇØ¼­ ÀϰýÀÛ¾÷ Çü½ÄÀ¸·Î ÆÄÀÏÀ» ¾÷/´Ù¿î·Îµå ÇÏ´Â ÇüÅ·Π»ç¿ëµÉ ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ÀÏÀ» ÇÏ´Â ½ºÅ©¸³Æ®¸¦ ÀÛ¼ºÇϱâ À§Çؼ­´Â expect¿Í °°Àº ÅøÀ» ÀÌ¿ëÇØ¾ß Çϴµ¥, Á¦´ë·Î ÀÛµ¿ÇÏ´Â ÇÁ·Î±×·¥À» Â¥±â¶õ ¿©°£ ¾î·Á¿î°Ô ¾Æ´Ï´Ù. ¼­¹öÀÇ Æ¯¼º¿¡ µû¶ó¼­ ÇÁ·Î±×·¡¹Ö ±â¹ýÀÌ ´Þ¶óÁ®¾ß Çϸç, ƯÈ÷ ¿¡·¯Ã³¸®°¡ ¸Å¿ì Èûµé±â ¶§¹®ÀÌ´Ù. (ncftp¿Í °°Àº ÇÁ·Î±×·¥Àº ½ºÅ©¸³Æ® ÇüÅ·Π»ç¿ë°¡´ÉÇÑ ncftpput, ncftpget'°ú °°Àº ÅøÀ» Á¦°øÇÑ´Ù.)

httpget.cc¿Í Áߺ¹µÇ´Â ³»¿ëµéÀº »©°í ¼³¸íÇϵµ·Ï ÇϰڴÙ. ÀÌ ÇÁ·Î±×·¥Àº ¿ø°ÝÁöÀÇ ÆÄÀÏÀ» ·ÎÄÿ¡ ÀúÀåÇÏÁö´Â ¾Ê´Â´Ù. ÆÄÀÏÀ» ÀоîµéÀ̰í, ±× Å©±â¸¸ Ãâ·ÂÀ» ÇÑ´Ù.
size_t showSize(...); 
curl_esay_setopt(ctx, CURLOPT_WRITEFUNCTION, showSize); 
 
CURLOPT_WRITEFUNCTIONÀº ¿ø°ÝÁö ÆÄÀÏÀ» ´Ù¿î·Îµå ÇÒ²² È£ÃâÇÒ ÇÔ¼ö¸¦ Á¤ÀÇÇϱâ À§Çؼ­ »ç¿ëÇÑ´Ù.

ÀÌÁ¦ ´Ù¿î·ÎµåÇÒ ÆÄÀϰ¹¼ö¸¸Å­ for·çÇÁ¸¦ µ¹¸é¼­ ÆÄÀÏÀ» ´Ù¿î¹Þ´Â´Ù. ¿ì¼± CURLOPT_URLÀ» ÀÌ¿ëÇØ¼­ ¿¬°áÀ» ½ÃµµÇÒ ¼­¹öÀ̸§À» Á¤ÇØÁØ´Ù. CURLOPT_WRIDATE ´Â CURLOPT_WRITEFUNCTION¸¦ ÀÌ¿ëÇØ¼­ Á¤ÀÇµÈ ÄݹéÇÔ¼ö - showSize() -¸¦ ÇÒ´çÇØ¼­ ÀÎÀÚ·Î ÁÖ¾îÁø XferInfo°´Ã¼¿¡ µ¥ÀÌÅ͸¦ ¾´´Ù.
class XferInfo 
{ 
    void add(int more); 
    int getBytesTransferred(); 
    int getTimesCalled(); 
}; 
... 
 
XferInfo info; 
curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &info); 
 

±×·³ ½ÇÁúÀûÀ¸·Î µ¥ÀÌÅ͸¦ ¹Þ¾Æ¼­ ó¸®ÇÏ´Â showSize ÄݹéÇÔ¼ö¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸µµ·Ï ÇÏÀÚ.
extern "C" 
size_t showSize 
{ 
    void *source, 
    size_t size, 
    size_t nmemb, 
    void *userData 
} 
 

source´Â ÀоîµéÀÎ ½ÇÁ¦ µ¥ÀÌÅÍ´Ù. ÀоîµéÀÎ µ¥ÀÌÅÍ´Â NULLÀ» Æ÷ÇÔÇÏ´Â ÀÌÁøµ¥ÀÌÅͰ¡ µÉ ¼ö ÀÖÀ¸¹Ç·Î, char *Çü ´ë½Å void * ÇüÀ» »ç¿ëÇß´Ù. ÀоîµéÀÏ µ¥ÀÌÅÍÀÇ Å©±â´Â size*nmemb¸¦ ÅëÇØ °è»êÇÑ´Ù.

userData´Â CURLOPT_WRITEDATA ¿¡ ÀÇÇØ¼­ ÇÒ´çµÈ, ÀڷᱸÁ¶·Î ¿ì¸®´Â ¿©±â¿¡ ÇÊ¿äÇÑ Á¤º¸ - ÀоîµéÀÎ ÆÄÀÏÀÇ Å©±â - ¸¦ ÀûÀ» °ÍÀÌ´Ù. userDataÀڷᱸÁ¶ ´ë½Å¿¡ ÆÄÀÏ¿¡ ¾²±æ ¿øÇÑ´Ù¸é FILE *À» ³Ñ±â¸é µÈ´Ù. usrData´Â void *ÇüÀ̹ǷΠ¹Ýµå½Ã ij½ºÆ® ÇØÁÖ¾î¾ß ÇÑ´Ù.
extern "C" 
size_t showSize(...) 
{ 
    XferInfo *info = static_cast<XferInfo *>(userData); 
    const int bufferSize = size * nmemb; 
    info->add(bufferSize); 
} 
 
ÀÌÁ¦ ¿ì¸®°¡ ¸¸µç ÄݹéÇÔ¼ö´Â ÀоîµéÀÎ ÆÄÀÏÀÇ Å©±â¸¦ (size*nmemb)·Î °è»êÇØ¼­ µÇµ¹·ÁÁÙ °ÍÀÌ´Ù. ¶ÇÇÑ ÀÌ ÇÔ¼ö´Â bufferSize¸¦ µÇµ¹·ÁÁÖ°Ô µÇ´Âµ¥, libCURLÀº ÄݹéÇÔ¼öÀÇ ¸®Åϰª°ú Àü¼Û¹ÞÀº ½ÇÁ¦ µ¥ÀÌÅÍÀÇ Å©±â¸¦ ºñ±³Çؼ­ Ʋ¸±°æ¿ì 0À» ¸®ÅÏÇØÁÖ°Ô µÈ´Ù. ÀÌ·±½ÄÀ¸·Î µ¥ÀÌÅ͸¦ Á¤»óÀûÀ¸·Î ¹Þ¾Ò´ÂÁö¸¦ üũÇÒ ¼ö ÀÖ´Ù.

ÀÌÁ¦ curl_easy_performÀ» ÀÌ¿ëÇØ¼­ URL¿¡ ¿¬°áÇØ¼­ µ¥ÀÌÅ͸¦ ¹Þ¾Æ¿À°í ÄݹéÇÔ¼ö¸¦ ½ÇÇà½ÃŰ¸é µÈ´Ù.
/* 
 
sample for O'ReillyNet article on libcURL: 
    {TITLE} 
    {URL} 
    AUTHOR: Ethan McCallum 
 
 
anon ftp/download (scenario: fetch remote file) 
 
ÀÌ ÄÚµå´Â Ubuntu ¸®´ª½º Kernel 2.6.15¿¡¼­ 
libcURL ¹öÁ¯ 7.15.1·Î Å×½ºÆ® µÇ¾ú´Ù. 
2006³â 8¿ù 3ÀÏ 
 
*/ 
 
#include<iostream> 
#include<string> 
#include<sstream> 
#include<list> 
 
extern "C" { 
    #include<curl/curl.h> 
} 
 
// - - - - - - - - - - - - - - - - - - - - 
 
typedef std::list< std::string > FileList ; 
 
enum { 
    ERROR_ARGS = 1 , 
    ERROR_CURL_INIT = 2 
} ; 
 
enum { 
    OPTION_FALSE = 0 , 
    OPTION_TRUE = 1 
} ; 
 
// - - - - - - - - - - - - - - - - - - - - 
 
// ÄݹéÇÔ¼ö¿¡¼­ »ç¿ëÇÒ »ç¿ëÀÚ Á¤ÀÇ °´Ã¼  
class XferInfo { 
 
    private: 
    int bytesTransferred_ ; 
    int invocations_ ; 
 
    protected: 
    // empty 
 
    public: 
    XferInfo(){ 
 
        reset() ; 
 
    } // ctor 
 
    /// reset counters 
    void reset(){ 
 
        bytesTransferred_ = 0 ; 
        invocations_ = 0 ; 
 
        return ; 
 
    } // reset() 
 
    /// add the number of bytes transferred in this call 
    void add( int more ){ 
 
        bytesTransferred_ += more ; 
        ++invocations_ ; 
 
        return ; 
 
    } // add()     
 
    /// get the amount of data transferred, in bytes 
    int getBytesTransferred() const { 
        return( bytesTransferred_ ) ; 
    } // getBytesTransferred() 
 
    /// get the number of times add() has been called 
    int getTimesCalled(){ 
        return( invocations_ ) ; 
    } // getTimesCalled() 
} ; 
 
// - - - - - - - - - - - - - - - - - - - - 
 
 
// C++ ¿¡¼­ CÇÔ¼ö¸¦ ¸µÅ©½Ã۱â À§Çؼ­´Â, "extern C"¸¦ ÀÌ¿ëÇØ¾ß ÇÑ´Ù. 
extern "C" 
size_t showSize( void *source , size_t size , size_t nmemb , void *userData ){ 
 
    // this function may be called any number of times for even a single 
    // transfer; be sure to write it accordingly. 
 
    // source is the actual data fetched by libcURL; cast it to whatever 
    // type you need (usually char*).  It has NO terminating NULL byte. 
 
    // we don't touch the data here, so the cast is commented out 
    // const char* data = static_cast< const char* >( source ) ; 
 
    // userData is called "stream" in the docs, which is misleading: 
    // that parameter can be _any_ data type, not necessarily a FILE* 
    // Here, we use it to save state between calls to this function 
    // and track number of times this callback is invoked. 
    XferInfo* info = static_cast< XferInfo* >( userData ) ; 
 
    const int bufferSize = size * nmemb ; 
 
    std::cout << '\t' << "showSize() called: " << bufferSize << " bytes passed" << std::endl ; 
 
    // ... pretend real data processing on *source happens here ... 
 
    info->add( bufferSize ) ; 
 
         
    /* 
    return some number less than bufferSize to indicate an 
    error (xfer abort) 
     
    nicer code would also set a status var (in userData) for the 
    calling function 
    */ 
 
    return( bufferSize ) ; 
 
} // showSize() 
 
 
// - - - - - - - - - - - - - - - - - - - - 
 
 
int main( const int argc , const char** argv ){ 
 
    if( argc < 3 ){ 
        std::cerr << "test of libcURL: anonymous FTP" << std::endl ; 
        std::cerr << " Usage: " << argv[0] << " {server} {file1} [{file2} ...]" << std::endl ; 
        return( ERROR_ARGS ) ; 
    } 
 
    // remote FTP server 
    const char* server = argv[1] ; 
 
    const int totalTargets = argc - 2 ; 
 
    std::cout << "Attempting to download " << totalTargets 
        << " files from " << server << std::endl 
    ; 
 
 
    curl_global_init( CURL_GLOBAL_ALL ) ; 
 
 
    CURL* ctx = curl_easy_init() ; 
 
    if( NULL == ctx ){ 
        std::cerr << "Unable to initialize cURL interface" << std::endl ; 
        return( ERROR_CURL_INIT ) ; 
    } 
 
    /* BEGIN: global handle options */ 
 
    // handy for debugging: see *everything* that goes on 
    // curl_easy_setopt( ctx , CURLOPT_VERBOSE, OPTION_TRUE ) ; 
 
    // no progress bar: 
    curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , OPTION_TRUE ) ; 
 
    // what to do with returned data 
    curl_easy_setopt( ctx , CURLOPT_WRITEFUNCTION , showSize ) ; 
 
    XferInfo info ; 
 
    for( 
        int ix = 2 ; 
        ix < argc ; 
        ++ix 
    ){ 
 
        const char* item = argv[ ix ] ; 
 
        // zero counters for each file 
        info.reset() ; 
 
 
        // target url: concatenate the server and target file name 
        urlBuffer.str( "" ) ; 
        urlBuffer << "ftp://" << server << "/" << item << std::flush ; 
 
        std::cout << "Trying " << urlBuffer.str() << std::endl ; 
 
        const std::string url = urlBuffer.str() ; 
 
        curl_easy_setopt( ctx , CURLOPT_URL,  url.c_str() ) ; 
 
        // set the write function's user-data (state data) 
        curl_easy_setopt( ctx , CURLOPT_WRITEDATA , &info ) ; 
 
 
        // action! 
 
        const CURLcode rc = curl_easy_perform( ctx ) ; 
 
        // for curl v7.11.x and earlier, look into 
        // curl_easy_setopt( ctx , CURLOPT_ERRORBUFFER , /* char array */ ) ; 
        if( CURLE_OK == rc ){ 
            std::cout << '\t' << "xfer size: " << info.getBytesTransferred() << " bytes" << std::endl ; 
            std::cout << '\t' << "Callback was invoked " << info.getTimesCalled() << " times for this file" << std::endl ; 
        } else { 
            std::cerr << "Error from cURL: " << curl_easy_strerror( rc ) << std::endl ; 
        } 
 
        std::cout << std::endl ; 
 
    } 
 
 
    // cleanup 
    curl_easy_cleanup( ctx ) ; 
    curl_global_cleanup() ; 
 
    return( 0 ) ; 
 
} // main() 
 
 

5 FTP ¾÷·Îµå

À̹ø¿¡ ¸¸µé ÇÁ·Î±×·¥Àº FTP È£½ºÆ®¿¡ ¿¬°áÇØ¼­ ÆÄÀÏÀ» Upload ÇÏ´Â ÀÏÀ» ÇÑ´Ù. FTPÈ£½ºÆ®¿¡ Á¢±ÙÇϱâ À§Çؼ­´Â hostÀÇ µµ¸ÞÀÎ À̸§°ú ·Î±×ÀÎÀ» À§ÇÑ ¾ÆÀ̵ð¿Í ÆÐ½º¿öµå°¡ ÇÊ¿äÇÏ´Ù. Á¦´ë·ÎµÈ ÇÁ·Î±×·¥À̶ó¸é ¼³Á¤ÆÄÀϵîÀ» ÅëÇØ¼­ À̵é Á¤º¸¸¦ ÀÔ·Â¹Þ¾Æ¾ß °ÚÁö¸¸, ¿©±â¿¡¼­´Â ÆíÀÇ»ó ¼Ò½º³»¿¡ ÇϵåÄÚµùÇϵµ·Ï ÇϰڴÙ. Ÿ°Ù URL¿¡ fileÀ» ¾÷·ÎµåÇÏ´Â °ÍÀº ´ÙÀ½°ú °°ÀÌ ±â¼úµÈ´Ù.
ftp://host/file 
 

·Î±×ÀÎÀ» À§ÇÑ ¾ÆÀ̵ð¿Í ÆÐ½º¿öµå´Â CURLOPT_USERPWD¸¦ ÀÌ¿ëÇØ¼­ ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. À̵é Á¤º¸´Â ´ÙÀ½°ú °°ÀÌ ±â¼úµÉ °ÍÀÌ´Ù.
login:password 
 

ÃÖÁ¾ÀûÀ¸·Î ´ÙÀ½°ú °°Àº URLÁ¤º¸¸¦ °¡Áö°Ô µÈ´Ù.
ftp://login:password@host/file 
 

libCURLÀº ÆÄÀÏÀ» Àü¼ÛÇÏ´Â °Í »Ó¸¸ ¾Æ´Ï¶ó. ftp¼­¹ö¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Â mkdir°ú °°Àº ¸í·Éµµ ¹®Á¦¾øÀÌ »ç¿ëÇÒ ¼ö ÀÖ´Ù. »ç¿ëÇÒ ¸í·ÉÀº curl_slist ¿¡ ¸µÅ©µå¸®½ºÆ® ÇüÅ·ΠÀúÀåÇÑ´Ù.
struct curl_slist *command=NULL; 
command = curl_slist_append( commands, "mkdir /some/path"); 
command = curl_slist_append( commands, "mkdir /another/path"); 
 
¹°·Ð ÀÌµé ¸í·ÉÀÌ ½ÇÇàÇϱâ À§Çؼ­´Â ·Î±×ÀÎ °úÁ¤À» ¿ì¼± °ÅÃÄ¾ß ÇÒ °ÍÀÌ´Ù. ÀÌÁ¦ CURLOPT_QUOTE¸¦ ÀÌ¿ëÇØ¼­ ¸í·ÉÀ» µî·Ï½ÃŰ¸é µÈ´Ù.
curl_easy_setopt(ctx, CURLPOST_QUOTE, commands); 
// curl_easy_performÀ» ÀÌ¿ëÇØ¼­ ftp ¼¼¼ÇÀ» ½ÃÀÛÇϰí 
// ¸í·ÉÀ» ½ÇÇàÇÑ´Ù. 
curl_slist_free_all(command); 
 


6 HTTP POST

HTTP POST´Â À¥À» ÅëÇØ¼­ Æûµ¥ÀÌÅ͸¦ ÁÖ°í¹Þ±â À§ÇÑ µ¥ÀÌÅÍ Àü¼Û¹æ¹ýÀÇ Çϳª´Ù. ÀÌ ¹®¼­ÀÇ ¸¶Áö¸· ¿¹Á¦·Î libCURLÀ» ÀÌ¿ëÇØ¼­ HTTP POST Çü½ÄÀÇ µ¥ÀÌÅ͸¦ Àü¼ÛÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸µµ·Ï ÇϰڴÙ. ¶ÇÇÑ »ç¿ëÀÚÁ¤ÀÇµÈ HTTP headerµµ Å×½ºÆ®Çϵµ·Ï ÇϰڴÙ. ¿ÏÀüÇÑ Å×½ºÆ®¸¦ À§Çؼ­´Â À¥¼­¹ö°¡ ±¸ÃàµÇ¾î ÀÖ¾î¾ß ÇÒ °ÍÀÌ´Ù.

POST·Î º¸³»´Â µ¥ÀÌÅÍ´Â key=valueÇüÅ·ΠµÇ¾î ÀÖÀ¸¸ç, °¢°¢ÀÇ key=value ´Â &¸¦ ÅëÇØ¼­ ±¸ºÐµÈ´Ù.
const char* postData="param1=value1¶m2=value2&..."; 
 
POST µ¥ÀÌÅÍ Àü¼ÛÀ» À§Çؼ­ CURLOPT_POSTFIELDS¿É¼ÇÀ» ¼³Á¤ÇÏ¸é µÈ´Ù.
curl_easy_setopt(ctx, CURLOPT_POSTFIELDS, postData); 
 

ÀÌÁ¦ CURLOPT_HTTPHEADER¸¦ ÀÌ¿ëÇØ¼­ »ç¿ëÀÚÁ¤ÀÇ HTTP Çì´õ¸¦ ¸¸µéµµ·Ï ÇÑ´Ù.
curl_sist * responseHeaders=NULL; 
 
responseHeaders = curl_slist_append( 
    responseHeaders, 
    "Expect: 100-continue" 
); 
 
curl_easy_setopt(ctx, CURLOPT_HTTPHEADER, responseHeaders); 
 
ÁÖÀÇ ÇÒ°ÍÀº libCURLÀº hidden Çʵ峪 JavaScript¿Í °°Àº Ŭ¶óÀ̾ðÆ®ÃøÀÇ ±â¼úµéÀ» »ç¿ëÇÏÁö ¸øÇÑ´Ù´Â Á¡ÀÌ´Ù. ¿¹¸¦µé¾î ÆûÀÔ·ÂÀ» ÇÏ°í³ª¼­ submit¹öưÀ» Ŭ¸¯ÇÏ¸é ÆûÀÇ °¢ Çʵ带 °Ë»çÇÏ´Â µîÀÇ ÀÚ¹Ù½ºÅ©¸³Æ®µîÀº ó¸®ÇÒ ¼ö ¾ø´Ù.

/* 
 
sample for O'ReillyNet article on libcURL: 
    {TITLE} 
    {URL} 
    AUTHOR: Ethan McCallum 
 
HTTP POST (e.g. form processing or REST web services) 
 
ÀÌ ÄÚµå´Â Ubuntu 6.06 Dapper Drake,   
libcURL 
This code was built/tested under Fedora Core 3, 
libcURL version 7.12.3 ȯ°æ¿¡¼­ Å×½ºÆ® µÇ¾ú´Ù. 
*/ 
 
#include<cstdio> 
#include<iostream> 
#include<string> 
#include<sstream> 
 
extern "C" { 
    #include<curl/curl.h> 
} 
 
// - - - - - - - - - - - - - - - - - - - - 
 
enum { 
    ERROR_ARGS = 1 , 
    ERROR_CURL_INIT = 2 
} ; 
 
enum { 
    OPTION_FALSE = 0 , 
    OPTION_TRUE = 1 
} ; 
 
enum { 
    FLAG_DEFAULT = 0  
} ; 
 
const char* targetUrl ; 
 
// - - - - - - - - - - - - - - - - - - - - 
 
int main( int argc , char** argv ){ 
 
    if( argc != 2 ){ 
        std::cerr << "test of libcURL: test an HTTP post" << std::endl ; 
        std::cerr << "(post data is canned)" << std::endl ; 
        std::cerr << " Usage: " << argv[0] << " {post url}" << std::endl ; 
        std::exit( ERROR_ARGS ) ; 
    } 
 
    targetUrl = argv[1] ; 
 
    curl_global_init( CURL_GLOBAL_ALL ) ; 
 
 
    CURL* ctx = curl_easy_init() ; 
 
    if( NULL == ctx ){ 
        std::cerr << "Unable to initialize cURL interface" << std::endl ; 
        return( ERROR_CURL_INIT ) ; 
    } 
 
    /* BEGIN: configure the handle: */ 
 
    // Target URL:  
    curl_easy_setopt( ctx , CURLOPT_URL,  targetUrl ) ; 
    // no progress bar: 
    curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , OPTION_TRUE ) ; 
 
    // ÀÀ´äµ¥ÀÌÅ͸¦ Ç¥ÁØÃâ·ÂÀ¸·Î º¸³½´Ù.  
    curl_easy_setopt( ctx , CURLOPT_WRITEDATA , stdout ) ; 
 
    // »ç¿ëÀÚ Á¤ÀÇ HTTP Çì´õ: create a linked list and assign 
    curl_slist* responseHeaders = NULL ; 
    responseHeaders = curl_slist_append( responseHeaders , "Expect: 100-continue" ) ; 
    responseHeaders = curl_slist_append( responseHeaders , "User-Agent: Some Custom App" ) ; 
    curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ; 
 
    // POST Data ¼³Á¤  
    // notice the URL-unfriendly characters (such as "%" and "&") 
    // URL¿¡¼­´Â '%', '&', ' '¿Í °°Àº ¹®ÀÚ¸¦ URL encoding ½ÃÄÑÁà¾ß ÇÑ´Ù. 
    // curl_escape ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ÀÎÄÚµùÇÒ ¼ö ÀÖ´Ù.  
    const char* postParams[] = { 
        "One"      , "this has % and & symbols" , 
        "Dos"      , "value with spaces" , 
        "Trois"    , "plus+signs+will+be+escaped" , 
        "Chetirye" , "fourth param..." , 
        NULL 
    } ;  
 
    // buffer for the POST params 
    std::ostringstream postBuf ; 
 
    const char** postParamsPtr = postParams ; 
 
    while( NULL != *postParamsPtr ) 
    { 
        // curl_escape( {string} , 0 ): replace special characters 
        // (such as space, "&", "+", "%") with HTML entities. 
        // ( 0 => "use strlen to find string length" ) 
        // remember to call curl_free() on the strings on the way out 
        char* key = curl_escape( postParamsPtr[0] , FLAG_DEFAULT ) ; 
        char* val = curl_escape( postParamsPtr[1] , FLAG_DEFAULT )  ; 
 
        std::cout << "Setting POST param: \"" << key << "\" => \"" << val << "\"" << std::endl ; 
        postBuf << key << "=" << val << "&" ; 
 
        postParamsPtr += 2 ; 
 
        // the cURL lib allocated the escaped versions of the 
        // param strings; we must free them here 
        curl_free( key ) ; 
        curl_free( val ) ; 
 
    } 
    postBuf << std::flush ; 
 
    // We can't really call "postBuf.str().c_str()" here, because 
    // the std::string created in the middle is a temporary.  In turn, 
    // the char* buf from its c_str() operation isn't guaranteed to 
    // be around after the function call. 
    // The solution: explicitly create the string. 
 
    // Larger (and/or better) code would use std::string::copy() to create 
    // a const char* pointer to pass to cURL, then clean it up later. 
    // e.g.: 
    //    const char* postData = new char*[ 1 + postBuf.tellg() ] ; 
    //     postBuf.str().copy( postData , std::string::npos ) ; 
    //  postData[ postBuf.tellg() ] == '\0' ; 
    const std::string postData = postBuf.str() ; 
 
    std::cout << "post data: " << postData << std::endl ; 
    curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str() ) ; 
 
    // do a standard HTTP POST op 
    // in theory, this is automatically set for us by setting 
    // CURLOPT_POSTFIELDS... 
    curl_easy_setopt( ctx , CURLOPT_POST , OPTION_TRUE ) ; 
 
    /* END: configure the handle */ 
    // action! 
    std::cout << "- - - BEGIN: response - - -" << std::endl ; 
    CURLcode rc = curl_easy_perform( ctx ) ; 
    std::cout << "- - - END: response - - -" << std::endl ; 
 
    // "curl_easy_strerror()" available in curl v7.12.x and later 
    if( CURLE_OK != rc ){ 
        std::cerr << '\t' << "Error from cURL: " << curl_easy_strerror( rc ) << std::endl ; 
    } 
 
    // cleanup 
    curl_slist_free_all( responseHeaders ) ; 
    curl_easy_cleanup( ctx ) ; 
    curl_global_cleanup() ; 
    std::exit( 0 ) ; 
} // main() 
 

À§ ÇÁ·Î±×·¥ÀÇ Å×½ºÆ®¸¦ À§Çؼ­ ´ÙÀ½°ú °°Àº phpÆäÀÌÁö¸¦ ¸¸µé¾ú´Ù.
<? 
    echo "SERVER Ons      : $One<br>\n"; 
    echo "SERVER Dos      : $Dos<br>\n"; 
    echo "SERVER Trois    : $Trois<br>\n"; 
    echo "SERVER Chetirye : $Chetirye<br>\n"; 
?> 
 
EmailÀ» ±âÀÔÇϸé, ´ñ±ÛÀÌ ¸ÞÀÏ·Î Àü´ÞµË´Ï´Ù.