FrontPage|FindPage|TitleIndex|RecentChanges|RSS Epoll Httpd
 

Project epHttpd #


1 Project epHttpd
1.1 HTTP ÇÁ·ÎÅäÄÝ : ?IExplorerÀÇ query¿Í ¼­¹ö response ºÐ¼®
1.2 ¼­¹öÀÇ ±¸Çö °³¿ä
1.3 ?TTextClient : Text/Line Protocol ±¸Çö
1.3.1 Text/Line ÇÁ·ÎÅäÄÝÀÇ ±âº»Å¬·¡½º ?TTextClient ±¸Çö
1.3.2 TTextClient:?:OnRead() ±¸Çö
1.4 ?THttpClient Ŭ·¡½º ±¸Çö
1.4.1 THttpClient:?:OnIdle()ÀÇ ±¸Çö : ¸Þ¼¼Áö ºÐ¼® & ó¸®
1.4.2 HTTP º»Ã¼ Àü¼Û
1.5 EpollSocket ÀÇ ¼öÁ¤
1.6 Signal Çڵ鷯
1.7 ¼Ò½º


¿©Å±îÁöÀÇ ÀÛ¾÷À» ±â¹ÝÀ¸·Î, ÀÌÁ¦´Â Epoll ±â¹ÝÀÇ httpd ¼­¹ö, Áï À¥¼­¹ö¸¦ ±¸ÇöÇغ¸·Á°í ÇÑ´Ù. ±×·¸´Ù°í Çؼ­ httpd 1.0/1.1 ÀÇ ÇÁ·ÎÅäÄÝÀ» ´Ù ±¸ÇöÇÏ´Â°Ô ¾Æ´Ï¶ó,

GET /
GET /index.html
GET /sample.jpg

°£´ÜÇÑ GET ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÏ´Â - ÆÄÀÏÀü¼Û¼­¹ö ¼öÁØÀÇ - °£´ÜÇÑ ¼­¹ö´Ù. ÀÌ ÇÁ·ÎÁ§Æ®´Â °øºÎ¸ñÀû ȤÀº »ó¿ëÀ¥¼­¹ö Á¦ÀÛ¸ñÀûÀ̶ó±âº¸´Ù´Â ´ÙÀ½À» ±¸ÇöÇϴµ¥ ÀÇÀÇ°¡ ÀÖ´Ù.

  1. Text ±â¹Ý ÇÁ·ÎÅäÄÝ ( ÇÑ ¶óÀÎÀÇ ³¡ÀÌ CR ȤÀº CR,LF·Î ³¡³ª´Â ÀϹÝÀûÀÎ ¶óÀαâ¹Ý )ÀÇ ±¸Çö
  2. Send Buffering À» ÅëÇÑ ´ë¿ë·® Àü¼Û
  3. epoll ½ºÆ®·¹½º Å×½ºÆ®
epoll°ü·ÃµÈ À¥ °­ÁÂ, »ùÇÃÇÁ·Î±×·¥µéÀ» ±¸ÇÒ ¼ö´Â ÀÖÀ¸³ª ¼¼¹ÐÇÑ ¿¡·¯Ã³¸®°¡ Æ÷ÇÔµÈ ¾ÈÁ¤µÈ ¼­¹ö¼Ò½º´Â ã±â Èûµé´Ù. ÀÌ ÇÁ·ÎÁ§Æ®´Â, ±âÁ¸ »ùÇÃÇÁ·Î±×·¥µéÀ» »ó¿ë¼­¹ö, Áï »ó¾÷Àû ÀÌ¿ëÀÌ °¡´ÉÇÑ ¼öÁØÀÇ ÇÁ·Î±×·¥µéÀ» ±¸ÇöÇÏ°íÀÚ ÇÑ´Ù. (°ú¿¬ ... -_-;;;)


1.1 HTTP ÇÁ·ÎÅäÄÝ : ?IExplorerÀÇ query¿Í ¼­¹ö response ºÐ¼® #

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, 
application/vnd.ms-powerpoint, application/x-shockwave-flash, */*
Accept-Language: ko
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461)
Host: 192.168.0.90:8000
Connection: Keep-Alive
[¿©±â¿¡ CRLF¸¸À» Æ÷ÇÔÇÏ´Â ÇϳªÀÇ ºó ¶óÀÎÀÌ ¹Ýµå½Ã Á¸Àç] 

±×³É ´Ü¼øÇÏ°Ô ´ýÇÁÇÏ´Â ¼­¹ö¸¦ µ¹·Á³õ°í, Internet Explorer¸¦ Á¢¼Ó½ÃÄѺôÙ. ±×·¨´õ´Ï À§¿Í°°Àº °á°ú°¡ ³ª¿Ô´Ù (192.168.0.90:8000Àº ÇÊÀÚ°¡ ¾²°íÀÖ´Â ¼­¹öÀÇ ÁÖ¼Ò:Æ÷Æ®¹øÈ£ ÀÌ´Ù). ¿©±â¼­ ¿ì¸®°¡ Áý¾î³»¾ß ÇÒ Ç׸ñÀº GET / ÀÌ°í ´Ù¸¥°Í¿¡´Â °ü½ÉÀÌ ¾ø´Ù. ÀÌ °á°ú´Â IE¿¡¼­ http://192.168.0.90:8000/ ÇÑ°ÍÀÌ°í ¸¸¾à http://192.168.0.90:8000/image.jpg ·Î ÀÔ·ÂÀ» Çϸé,
GET /image.jpg HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, 
application/vnd.ms-powerpoint, application/x-shockwave-flash, */*
Accept-Language: ko
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461)
Host: 192.168.0.90:8000
Connection: Keep-Alive
[¿©±â¿¡ CRLF¸¸À» Æ÷ÇÔÇÏ´Â ÇϳªÀÇ ºó ¶óÀÎÀÌ ¹Ýµå½Ã Á¸Àç]

ÀÌ·± ¿äûÀ» ¹Þ´Â´Ù. [http]HTTP Çì´õ¿¡ ´ëÇÑ º¸´Ù ÀÚ¼¼ÇÑ ¸µÅ©

ÀÌ¿¡ ´ëÇÑ ÀÀ´äÀº ´ÙÀ½°ú °°Àº ÇüŸ¦ ¶í´Ù.
HTTP/1.0 200 OK
Date: Thu, 03 May 1997 16:04:09 GMT 
Server: NCSA/1.4.2
MIME-version: 1.0
Content-type: text/html
Last-moidified: Thu, 03 May 1997 16:03:27 GMT
Content-length: 145
[¿©±â¿¡ CRLF¸¸À» Æ÷ÇÔÇÏ´Â ÇϳªÀÇ ºó ¶óÀÎÀÌ ¹Ýµå½Ã Á¸Àç]
[½ÇÁ¦ µ¥ÀÌÅÍ]

Áï, ¿ì¸®°¡ ¸¸µé ¼­¹ö´Â ÀÌ·±Çü½ÄÀÇ ÀÀ´äÀ» ÇØ ÁÖ¾î¾ß ÇÑ´Ù. ùÁÙÀÇ 200 À̶ó´Â ¼ýÀÚ´Â HTTP ÀÀ´äÄÚµå·Î ¼º°øÀÇ ÀǹÌÀÌ°í, ¸¸¾à¿¡ ÆÄÀÏÀ» ãÁö ¸øÇϸé 404, ¾ï¼¼½º±ÇÇÑÀÌ ¾øÀ¸¸é 403À» ¸®ÅÏÇÑ´Ù. Content-typeÀº ¿ì¸®°¡ ½÷ ÁÖ¾î¾ß ÇÒ ÀÚ·áÀÇ Çü½ÄÀε¥ text/hmtl, image/jpeg, ... ÀÇ Çü½Ä.

À§¿Í °°Àº http Çì´õ µÚ¿¡ ºóÁÙ Çϳª°¡ µé¾î°¡°í ½ÇÁ¦ ÆÄÀÏÀÇ ³»¿ëÀÌ ´ã±â°Ô µÈ´Ù.


1.2 ¼­¹öÀÇ ±¸Çö °³¿ä #

ephttpd´Â ´ÙÀ½°ú °°Àº ó¸® È帧À» °¡Áö°í ±¸ÇöÇÒ °ÍÀÌ´Ù.

  1. Ŭ¶óÀ̾ðÆ®°¡ ¿¬°áµÇ¸é 'GET ...' ÀÇ request¸¦ º¸³¾ °ÍÀÌ´Ù.
  2. ´Ù¸¥ ³»¿ëÀº ´Ù ¹«½ÃÇÏ°í GET µÚÀÇ urlÀ» ÃßÃâÇÑ´Ù.
  3. url·ÎºÎÅÍ ½ÇÁ¦ ÆÄÀÏÀ» ã¾Æº¸°í ÇØ´çÆÄÀÏÀ» ¿­¾î Àü¼ÛÇÑ´Ù.
ÀÌ °úÁ¤¿¡¼­, ¿©·¯°¡ÁöÀÇ º¸Á¶ ·çƾµéÀ» ÇÊ¿ä·Î ÇÏ¸ç ¸ðµÎ Á¦ÀÛÇÒ °ÍÀÌ´Ù.

  1. ÅؽºÆ® ÇÑÁÙÀ» °ø¹é±âÁØÀ¸·Î À߶󳻴 Token ÇÔ¼ö
  2. »ó´ë url·ÎºÎÅÍ ÆÄÀÏÀÇ Àý´ëÀ§Ä¡¸¦ ¾ò¾î³»´Â ÇÔ¼ö, ´Ü ÇØÅ·ÀÇ À§ÇèÀÌ Àֱ⿡ url¿¡¼­ ..µîÀ» °ÅºÎÇÏ´Â ±â´É ±¸Çö
  3. HTTP Çì´õ »ý¼º ÇÔ¼ö (»çÀÌÁî, ¼öÁ¤ÀÏÀÚ µî)
´Ù¸¸, ÀÌ ¼­¹ö°¡ ½ÇÁ¦ À¥¼­¹ö¸¦ ´ëüÇϱâÀ§ÇØ °³¹ßµÇ´Â °ÍÀÌ ¾Æ´Ï¹Ç·Î ´ÙÀ½ÀÇ °ÍµéÀº ±¸ÇöÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù.

  1. URLENCODE, URLDECODE : url Ç¥Áر԰ݿ¡ ¸ÂÃß±â À§ÇØ °ø¹éÀÌ %20·Î ´ëüµÈ °æ¿ìµî¿¡ ´ëÇÑ µðÄÚµù
  2. ÇѱÛÆÄÀÏÀ̸§Ã³¸® : url¿¡ Çѱ۵î Ư¼ö¹®ÀÚ°¡ Æ÷ÇԵǾúÀ» °æ¿ì¿¡ ´ëÇÑ Ã³¸®
  3. µð·ºÅ丮 ºê¶ó¿ì¡ : ÆÄÀÏÀ» ¿äûÇÑ°ÍÀÌ ¾Æ´Ï°í µð·ºÅ丮¸¦ ¿äûÇßÀ» °æ¿ì¿¡ ´ëÇÑ Ã³¸®
  4. CGI ÀÎÅÍÆäÀ̽º ±¸Çö
  5. php¿£Áøµî°úÀÇ ¿¬°á
  6. ·Î±ë
  7. ±âŸµîµî

1.3 ?TTextClient : Text/Line Protocol ±¸Çö #

ÀÏ´Ü °¡º±°Ô ¶°¿À¸£´Â ±¸Çö ¼ø¼­´Â ÀÌ·¸´Ù.

  1. ?OnIdle¿¡¼­, recvbuf.View(...)¸¦ ÅëÇØ ¶óÀκ극ÀÌÄ¿(CRLF)°¡ µé¾î¿Ô´ÂÁö È®ÀÎ
  2. µé¾î¿Ô´Ù¸é, ÇÑ ¶óÀÎ ²¨³»±â (View&Skip ȤÀº Pop)
ÇÏÁö¸¸, View ÇÔ¼ö ³»ºÎÀûÀ¸·Î º¹»ç¸¦ ¼öÇàÇϹǷΠ´ÜÁö ÇÑ ¶óÀÎÀÌ µé¾î¿Ô´ÂÁö¸¦ °Ë»çÇÏ´Â ¸ñÀûÀ¸·Î´Â ³¶ºñ°¡ ½ÉÇÏ´Ù. ±×·¡¼­, ?TBinQueueÀÇ ¼öÁ¤À» ÇÊ¿ä·Î ÇÑ´Ù.

»õ·Î¸¸µé Ŭ·¡½º´Â ?TTextQueue. ÀÚ¼¼ÇÑ ±¸ÇöÀº º°µµ ¹®¼­·Î Á¤¸®ÇÏ¿´´Ù(TextBuffering). ÀÌ Å¬·¡½º¸¦ ÀÌ¿ëÇÏ¿© ´ÙÀ½°ú °°Àº ¼ø¼­·Î ±¸ÇöÇÑ´Ù.

  1. ?OnRead¿¡¼­, µé¾î¿Â µ¥ÀÌÅ͸¦ ¹Ù·Î ?TextQueue¿¡ ³Ö´Â´Ù.
  2. ?OnIdle¿¡¼­, recvlist.empty()·Î µé¾î¿Â µ¥ÀÌÅÍ°¡ ÀÖ´ÂÁö È®ÀÎÇÏ°í ²¨³»¼­ ó¸®

1.3.1 Text/Line ÇÁ·ÎÅäÄÝÀÇ ±âº»Å¬·¡½º ?TTextClient ±¸Çö #

#define MAX_LINE 256
#define MAX_BUF 819200

class TTextClient : public TEpollClient
{
protected :
    TTextQueue *recvlist;
    TBinQueue  *sendbuf;
    int nin, nout;

    bool is_would_block;
    bool is_error;

    virtual int internalbuffersize(void) { return MAX_BUF; };
    virtual int Flush(void);

public :
    TTextClient(const int lfd, const char *laddr) : TEpollClient(lfd, laddr)
    {
        recvlist = new TTextQueue(MAX_LINE);
        sendbuf  = new TBinQueue(internalbuffersize());

        nin = nout = 0;
        is_would_block = is_error = false;
    };

    ~TTextClient()
    {
        delete recvlist;
        delete sendbuf;
    };

    virtual int OnWrite(void);
    virtual int OnRead(void);
    virtual int OnIdle(void);
    virtual int OnError(const int);
}; 

?TBasicClient¸¦ »ó¼Ó¹Þ¾Æ¼­ ±¸ÇöÇÏ·Á´Ù°¡, ¸î°¡Áö ¹ø°Å·Î¿î ¹®Á¦µéÀÌ À־ Binary¿ë°ú Text¿ëÀÇ ?BasicClient Ŭ·¡½º¸¦ °¢°¢ ¸¸µé±â·Î Çß´Ù. µÎ Ŭ·¡½ºÀÇ µ¿ÀÛ¹æ½ÄÀº ´Ù ¶È°°Áö¸¸, ?OnRead ¿¡¼­ ¹ÙÀ̳ʸ® ¹öÆÛ¸µÀ» ÇÏ´À³Ä ÅؽºÆ® ¹öÆÛ¸µÀ» ÇÏ´À³ÄÀÇ Â÷ÀÌÀÌ´Ù. ³ªÁß¿¡ ½Ã°£ÀÌ ´õ µÇ¸é (°ú¿¬ --;;) µÎ Ŭ·¡½ºÀÇ °øÅëºÐ¸ð¸¦ »Ì¾Æ³»¼­ ?TEpollClient - ?TBasicClient - ?TBinClient ¿Í ?TEpollClient - ?TBasicClient - ?TTextClientÀÇ Ã¼°è¸¦ °¡Áöµµ·Ï ±¸¼ºÇØ º¸°í´Â ½Í´Ù.

?TTextClient´Â sendbuffer¿¡ ´ëÇؼ­´Â ¹ÙÀ̳ʸ®¿Í ÅؽºÆ® ±¸ºÐ¾øÀÌ ¶È°°ÀÌ ¹ÙÀ̳ʸ®·Î ó¸®Çϵµ·Ï Çß´Ù. ´Ù¸¸ ³ªÁß¿¡ »ç¿ëÀÚ ÆíÀǸ¦ À§ÇØ ?SendText³ª ?SendLine °°Àº ¸Þ½îµå¸¦ Á¦°øÇØ ÁÙ °ÍÀÌ´Ù. recvbuffer´Â ¹ÙÀ̳ʸ®ÀÇ °æ¿ì¿Í ±¸ºÐÇϱâ À§ÇØ recvlist¶ó°í À̸§ºÙ¿´´Âµ¥ char *ÀÇ list±¸Á¶·Î ¼±¾ðÇÏ¿´´Ù.


1.3.2 TTextClient:?:OnRead() ±¸Çö #

int TTextClient::OnRead(void)
{   
    char buf[SIZE_OSBUF];
    int nread = read(fd, buf, SIZE_OSBUF);

    if(nread == 0) return EP_ERROR_READ_CLOSE;
    else if(nread < 0){
        if(errno == EAGAIN) return EP_ERROR_NONE;
        return EP_ERROR_READ_GEN;
    }
    if(recvlist->Push(nread, buf) < 0){
//        cout << "read overflow\n";
        return EP_ERROR_READ_OVERFLOW;
    }
        
    nin += nread;

    return EP_ERROR_NONE;
}; 

¹ÙÀ̳ʸ® Ŭ·¡½º¿Í Å©°Ô ´Ù¸£Áö ¾Ê´Ù. recvbuf´ë½Å¿¡ recvlist(Áï, ?TTextQueue)¿¡ µ¥ÀÌÅ͸¦ ³ÖÀ» »ÓÀÌ´Ù. ¸¶Âù°¡Áö·Î ÀÌ °÷¿¡¼­ ¹Ù·Î µé¾î¿À´Â µ¥ÀÌÅ͸¦ ºÐ¼®&ó¸®ÇÏÁö ¾Ê°í ¼ÒÄÏ¿¡¼­ µ¥ÀÌÅ͸¦ ÀÐ¾î ½×´Â ÀÛ¾÷¸¸À» Çϵµ·Ï Çß´Ù. ½ÇÁ¦ ó¸®&ºÐ¼®Àº ?OnIdle ¿¡¼­ ¼öÇàÇÒ °ÍÀÌ´Ù.

recvlist->PushÀÇ ¸®ÅÏ°ªÀÌ 0 ÀÎ °æ¿ì´Â, µ¥ÀÌÅÍ´Â µé¾î¿ÔÁö¸¸ ÇÑ ¶óÀÎÀ» ä¿ìÁö ¸øÇÑ °æ¿ì·Î ºÁ¾ßÇϹǷΠ¿¡·¯Ã³¸® ÇÏÁö ¾Ê°í, 0 º¸´Ù ÀÛÀº °æ¿ì¿¡ ¿¡·¯ ó¸®Çϵµ·Ï ÇÏ¿´´Ù. ¿¡·¯´Â µÎ Á¾·ùÀÏÅÙµ¥ BUF_ERROR_MAX_LINE (ÇÑ ¶óÀÎÀÌ ³Ê¹« ±æ´Ù)¿Í BUF_ERROR_MAX_LIST (º¸°üµÈ ¶óÀÎ ¼ýÀÚ°¡ ³Ê¹« ¸¹´Ù). Ưº°È÷ ó¸®ÇÏÁö ¾Ê°í ¿¡·¯¸®ÅÏ ÇÏ°Ô ÇÏ¿´´Âµ¥ ÀÌ °á°ú·Î ÀÌ ¼ÒÄÏÀÇ ¿¬°áÀº ²÷¾îÁú °ÍÀÌ´Ù.

ÀÌ µÎ Á¾·ùÀÇ ¿¡·¯ 󸮴 ³­°¨ÇÏ´Ù. ù°´Â ÇÁ·ÎÅäÄÝ ±Ô¾àÀ» ÁؼöÇÏÁö ¾Ê¾ÒÀ» È®·üÀÌ ³ô°í µÎ¹ø°´Â ¼­¹ö°¡ ó¸®ÇÏ´Â °Íº¸´Ù ÈξÀ ¸¹Àº µ¥ÀÌÅÍ°¡ ¼ö½ÅµÈ °æ¿ìÀÏ È®·üÀÌ ³ô´Ù. ÀÌ µÎ°¡Áö »óȲÀÌ ÀϾÁö ¾Êµµ·Ï ÇÏ´Â°Ô ÁÁ°ÚÁö¸¸, ¿©À¯°¡ µÈ´Ù¸é »ó¼öµéÀ» ³Ë³ËÇÑ ¼ýÀÚ·Î Àâ¾ÆÁÖ¸é ¿À·ù¸¦ ÃÖ´ëÇÑ ÁÙÀÏ ¼ö ÀÖÀ» °ÍÀÌ´Ù. (MAX_LINE, MAX_LIST in buffer.h)


1.4 ?THttpClient Ŭ·¡½º ±¸Çö #

?TTextClient ¸¦ ±â¹ÝÀ¸·Î, ?THttpClient¸¦ ±¸ÇöÇÑ´Ù. ´ëºÎºÐÀÇ ÀÔÃâ·Â󸮴 ?TTextClient°¡ ÇØÁÙ°ÍÀÌ°í, ?THttpClient´Â ?OnIdle ¸¸ ±¸ÇöÇÑ´Ù.


1.4.1 THttpClient:?:OnIdle()ÀÇ ±¸Çö : ¸Þ¼¼Áö ºÐ¼® & ó¸® #

¿©±â±îÁö Çؼ­ Ŭ¶óÀ̾ðÆ®¿¡¼­ º¸³½ µ¥ÀÌÅ͸¦ ¶óÀκ°·Î ¼Õ¿¡ ³Ö¾ú´Ù! °¢ ¶óÀÎÀ» ¾î¶»°Ô ó¸®ÇÒ °ÍÀΰ¡´Â ¿ª½Ã »ç¿ëÀÚÀÇ ¸òÀÌ´Ù. °è¼ÓÇؼ­ ¿Ï¼ºµµ ³ôÀº À¥¼­¹ö·Î ¸¸µé¾î °¡°íÀÚ ÇÑ´Ù¸é, ºóÁÙÀÌ µé¾î¿Ã¶§±îÁö¸¦ ÇϳªÀÇ Çì´õ±¸Á¶·Î ¹­¾î °ü¸®ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù. ÀÌ ±Û¿¡¼­´Â °£´ÜÇÏ°Ô 'GET' À¸·Î ½ÃÀ۵Ǵ ¶óÀο¡¸¸ °ü½ÉÀ» °¡Áö°í ºÐ¼® ó¸®ÇÒ °ÍÀÌ´Ù.

  1. ÇÑ ¶óÀξ¿ ²¨³»¼­ óÀ½ 3 ¹ÙÀÌÆ®°¡ 'GET' À¸·Î ½ÃÀÛÇÏ´ÂÁö °Ë»çÇÏ°í,
  2. °ø¹éÀ» ±âÁØÀ¸·Î ÅäÅ«À» ºÐ¸®ÇÏ¿©,
  3. µÎ¹ø° ÅäÅ«À» ±âÁØÀ¸·Î Àý´ë ÆÄÀÏ°æ·Î¸¦ ¿Ï¼º
  4. Àü¼Û·çƾÀ¸·Î Àü´Þ

ÇÑ ¶óÀξ¿ ²¨³»¼­ ó¸®Çϱâ
    ....
    while(! recvlist->empty()){
       char buf[MAX_LINE];

       if(recvlist->Pop(buf) < 1) break;

       .... 
    }
    .... 

ȤÀº,
    ....
    char buf[MAX_LINE];

    while( recvlist->Pop(buf) > 0 ){
        ....

    }
    .... 

ÀÌ·±½ÄÀ¸·Î ÇѶóÀξ¿ ²¨³» ó¸®ÇÑ´Ù. TTextQueue:?:PopÀº ²¨³¾ ¶óÀÎÀÌ ¾øÀ»°æ¿ì 0À», Á¤»óÀΰæ¿ì 1À» ¸®ÅÏÇÑ´Ù.


ÅäÅ«ºÐ¸®

ÅäÅ«ºÐ¸®´Â ¾ÆÁÖ¾ÆÁÖ ¸¹ÀÌ ¾²ÀÌ´Â ±â¼úÀÌ´Ù. ±×·¡¼­ ³¯Àâ¾Æ µû·Î Á¤¸®¸¦ ÇÒ °ÍÀÌÁö¸¸, ¿©±â¼­´Â strchrÀ» ÀÌ¿ëÇؼ­ °£´ÜÈ÷ ±¸ÇöÇß´Ù. ÀÌ ÇÔ¼ö´Â °ø¹éÀ» ±âÁØÀ¸·Î À߶󳽴ÙÀ½ vector ÄÁÅ×À̳ʿ¡ ´ã¾Æ ÁØ´Ù. strtok ÇÔ¼ö°¡ ÀÌ·²¶§ ¾²¶ó°í ÀÖ±â´Â ÇÏÁö¸¸ ¿©·¯°¡Áö ¹ø°Å·Î¿î ¹®Á¦°¡ À־ »ç¿ëÇÏÁö ¾Ê¾Ò´Ù.
int tokens(const char *s, vector<const char *> &vToken)
{
    vToken.clear();
    char *sptr, *nptr;
    int nt;

    int n, nsize = strlen(s);

    while(*s){
        sptr = strchr(s, ' ');
        if(!sptr) break;

        nt = sptr - s;
        nptr = new char[nt+1];
        strncpy(nptr, s, nt);
        nptr[nt] = 0;
        vToken.push_back(nptr);

        s = ++sptr;
    }
    if(*s) vToken.push_back(s);

    return vToken.size();
} 

vTokenÀÌ Æ÷ÀÎÅÍÀÇ ¹è¿­À̹ǷÎ, »èÁ¦ÇÒ¶§¿¡ Á¶±Ý ¹ø°Å·Ó´Ù. ¹ü¿ë ÄÁÅ×ÀÌ³Ê »èÁ¦ÇÔ¼ö Sequence Delete¸¦ ÀÌ¿ëÇÏ¿© »èÁ¦Ã³¸®ÇÑ´Ù. Âü°í : http://oopsla.snu.ac.kr/~sjjung/stl/ptr_0001.htm

template <class ForwardIterator>
void sequence_delete(ForwardIterator first, ForwardIterator last)
{
    while (first != last)
        delete *first++;
} 


¸Þ¼¼ÁöºÐ¼®À» ÅëÇØ ¿äû url ¾ò¾î³»±â
    while(recvlist->Pop(buf) > 0){
        if( strncmp(buf, "GET", 3) ) continue;

        do {
            std::vector<const char *> ve;
            ntoken = tokens(buf, ve);

            if(ntoken < 2) continue;

            msgGET(ve[1]);
        } while(0);
    } 

ÇÑÁÙ¾¿ ²¨³»¼­, óÀ½ ¼¼±ÛÀÚ°¡ 'GET'À¸·Î ½ÃÀ۵ǴÂÁö ÆľÇÇÑÈÄ °ø¹é±âÁØÀ¸·Î À߶󳽴Ù. ÀÌ °ªÀ» msgGET : GET ¸Þ¼¼Áöó¸®ÇÔ¼ö·Î Àü´ÞÇÑ´Ù. do... while(0) Àº Àǹ̾øÀÌ »ç¿ë - ?OnIdle ÀÌ ¼öµµ¾øÀÌ È£ÃâµÇ¹Ç·Î º¯¼ö»ý¼ºÀ» È¿À²ÀûÀ¸·Î Çϱâ À§ÇØ »ç¿ëÇÏ¿´´Ù.

=== HTTP Çì´õ Àü¼Û=== msgGET()
#define DEFAULT_DOC "index.html"

int THttpClient::msgGET(const char *url)
{
    int httpcode = 200;

    char filename[MAX_LINE], mime[MAX_LINE];
    getcwd(filename, MAX_LINE);

    strcat(filename, url); // make the full filename

    // url ÀÇ ¸¶Áö¸·ÀÌ / ¶ó¸é,
    if( filename[strlen(filename) - 1]  == '/' ) strcat (filename, DEFAULT_DOC);
    // url ¿À·ù°Ë»ç
    if( (filename[0] != '/') || (strstr(filename, "..") != NULL) ) httpcode = 500;

    ....   

¿äû url·ÎºÎÅÍ Ç®Æо²ÆÄÀϳ×ÀÓÀ» ¸¸µé¾î³½´Ù. ¿äûurlÀÇ ³¡ÀÌ '/' ÀÏ °æ¿ì (¿¹¸¦ µé¾î http://www.yahoo.com/)´Â µðÆúÆ® µµÅ¥¸ÕÆ® À̸§À¸·Î ÇÑ´Ù. À¥ºê¶ó¿ìÀú´Â Ç×»ó urlÀÌ '/'·Î ½ÃÀÛÇϵµ·Ï Á¶Á¤À» Çϴµ¥, ÀÌ ¹®ÀÚ·Î ½ÃÀÛÇÏÁö ¾Ê°Å³ª url ¿¡ '..'ÀÌ Æ÷ÇԵǴ °æ¿ì´Â ¿¡·¯·Î ó¸®Çϵµ·Ï ÇÏ¿´´Ù - ¿¡·¯¶ó°í ÇÏ´õ¶óµµ 500 ÄÚµå·Î ÀÀ´äÇØ ÁÖµµ·Ï ÇÑ´Ù.

ÆÄÀÏ»óÅ °Ë»ç
    // stat ¾ò¾î³¿
    struct stat fileinfo;

    if ( stat(filename, &fileinfo) == -1)
    {
        switch(errno){
        case ENOENT : // file not found
            httpcode = 404;
            break;

        case EACCES : // permission denied
            httpcode = 403;
            break;

        default : // some error
            httpcode = 500;
        }
        ResponseHeader(httpcode);
    } else {
        get_http_mime_type(filename, mime);
        ResponseHeader(httpcode, fileinfo.st_mtime, fileinfo.st_size, mime);
    }

unstd.hÀÇ stat ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­, ÆÄÀÏ »óŸ¦ °£´ÜÈ÷ Á¶»çÇÑ´Ù. ÆÄÀÏÀÇ Á¸Àç À¯¹«¿Í ¾ï¼¼½º ±ÇÇÑ°Ë»ç, ÆÄÀÏŸÀÔ(¸µÅ©ÀÎÁö..µîµî)À» °Ë»çÇÒ ¼ö ÀÖ°í, ¼º°øÇϸé struct stat¿¡ ÆÄÀÏÀÇ »ó¼¼Á¤º¸ (»ý¼º³¯Â¥, ¼ÒÀ¯ÁÖ, ±ÇÇÑ µîµî)¸¦ ¾Ë·ÁÁִµ¥ ÀÌ °ªµéÀ» ÀÀ´äÇÔ¼ö¿¡ Àü´ÞÇϵµ·Ï Çß´Ù. get_http_mime_type À̶ó´Â ÇÔ¼ö¸¦ Àӽ÷ΠÇϳª ¸¸µé¾ú´Âµ¥, ½Ã½ºÅÛ¿¡¼­ º°µµ·Î °ü¸®¸¦ ÇϹǷΠ½Ã°£À̵ȴٸé(^^;) ½Ã½ºÅÛ¿¡ µî·ÏµÈ ¸¶ÀÓÀ» ¾ò¾î³»µµ·Ï °íÃÄ º¸ÀÚ.

mime ¾ò¾î³»±â
#define MIME_DEFAULT  "text/plain"

int get_http_mime_type(const char *file, char *outbuffer)
{
    char *ptr = strrchr(file, '.');

    if(! ptr)                     strcpy(outbuffer, MIME_DEFAULT);
    else if(!strcmp(ptr, "jpg"))  strcpy(outbuffer, "image/jpeg");
    else if(!strcmp(ptr, "html")) strcpy(outbuffer, "text/html");
    else                          strcpy(outbuffer, MIME_DEFAULT);

    return 1;
} 

´Ü¼øÈ÷ È®ÀåÀÚ¸¦ °Ë»çÇؼ­ ¸î°¡Áö Á¾·ùÁß¿¡¼­ ÇØ´çµÇ´Â ¸¶ÀÓÀ» ¸®ÅÏÇϵµ·Ï Çß´Ù.


?ResponseHeader : ÀÀ´ä Çì´õ Àü¼Û
int THttpClient::ResponseHeader(const int errcode, const time_t mtime, const int csize, const char *mime)
{
    char buf[MAX_LINE], errstr[MAX_LINE], datestr[MAX_LINE], mimestr[MAX_LINE];

    switch(errcode){
    case 200 : strcpy(errstr, "OK");
        break;
    case 404 : strcpy(errstr, "Object Not Found");
        break;
    case 403 : strcpy(errstr, "Permission Denied");
        break;
    case 500 : strcpy(errstr, "Internal Server Error");
        break;
    }

    time_t tt;
    time(&tt);
    get_http_gmtime_str(tt, datestr);

    sprintf(buf, "HTTP/1.0 %d %s\n"
                 "Date: %s GMT\n"
                 "Server: %s\n", errcode, errstr, datestr, SERVER);

    sendbuf->Push(strlen(buf), buf);

    if(errcode == 200){
        get_http_gmtime_str(mtime, datestr);

        sprintf(buf, "Last-modified: %s\n"
                     "Content-type: %s\n"
                     "Content-Length: %d\n" , datestr, mime, csize);

        sendbuf->Push(strlen(buf), buf);
    } else {
        sprintf(buf, "Content-Length: %d\n" , 0);
    }
    sendbuf->Push(2, CRLF);

    return 0;
} 

º¸´Â°Íó·³, Çì´õ³»¿ëÀ» ¸¸µé¾î³»´Â ÇÔ¼öÀÌ´Ù. Çì´õÀÇ ³¡Àº ºóÁÙÀ̹ǷÎ, ¸¶Áö¸·¿¡ ºóÁÙ Çϳª º¸³»ÁÖ´Â°Í ÀØÁö ¸»ÀÚ. Çì´õ³»¿ëÁß¿¡ ³¯Â¥°ü·ÃµÈ °÷ÀÌ 2°³°¡ Àִµ¥(Date: ¿Í Last-modified: ), HTTP ÀÀ´ä¿¡¼­, ÀÀ´ä½Ã°£ ¹× ÄÁÅÙÃ÷ÀÇ ÃÖÁ¾¼öÁ¤½Ã°£ Çü½ÄÀº GMT¸¦ ±âÁØÀ¸·Î ÇϹǷΠget_http_gmtime_strÇÔ¼ö¸¦ Á¦ÀÛÇÏ¿´´Ù.

int get_http_gmtime_str(const time_t tt, char *outbuffer)
{
    // Çü½Ä : Thu, 03 May 1997 16:04:09 

    char *dow[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

    struct tm *ttm = gmtime(&tt);

    sprintf(outbuffer, "%s, %02d %s %04d %02d:%02d:%02d",
        dow[ttm->tm_wday], ttm->tm_mday, mon[ttm->tm_mon],
        ttm->tm_year + 1900, ttm->tm_hour, ttm->tm_min, ttm->tm_sec
    );

    return 1;
} 

struct tm ÀÇ Çü½ÄÀº, °¡²û È¥¶õ½º·¯¿îµ¥ ¿äÀÏ, ¿ùÀº 0ºÎÅÍ ½ÃÀÛÇÏ°í, ¿¬µµ´Â 1900³âºÎÅÍ ½ÃÀÛÇÑ´Ù. ³ª¸ÓÁö°ªµéÀº ¿¹»óÇϴ´ë·Î »ó½ÄÀûÀÌÁö¸¸, ¿äÀÏ&¿ù&³âÀº ÁÖÀÇÇØ¾ß ÇÑ´Ù. ÀÌ ±¸Á¶Ã¼¿¡¼­ y2k ¹®Á¦´Â ¹ß»ýÇÏÁö ¾Ê´Â´Ù. GMT¸¦ ¾ò¾î³»±â À§ÇØ gmtimeÀ» È£ÃâÇߴµ¥, ÇöÀç ½Ã½ºÅÛÀÇ ·ÎÄÉÀÏ¿¡ ¸Â´Â ½Ã°£ (Áï, ÇöÀç½Ã°£)Àº localtimeÀ¸·Î ¾ò¾î³½´Ù.

ÀÌ·¸°Ô Çؼ­ Çì´õ Àü¼ÛÀº ¸¶¹«¸®ÇÏ°í, ÀÌÁ¦ ÄÁÅÙÃ÷ º»Ã¼¸¦ Àü¼ÛÇØ¾ß ÇÑ´Ù.


1.4.2 HTTP º»Ã¼ Àü¼Û #

º»Ã¼ Àü¼ÛÀº ÆÄÀÏÀ» Àо ±× ³»¿ëÀ» Àü¼ÛÇØÁÖ¸é µÈ´Ù. ½±´Ù? ÇÏÁö¸¸ °ñÄ¡¾ÆÇ ¹®Á¦°¡ Çϳª ¼û¾îÀÖ´Ù. ÆÄÀÏ »çÀÌÁî°¡ ¼¾µå¹öÆÛ »çÀÌÁ´Ù Å©´Ù¸é Sendbuffer overflow¿¡ Á÷¸éÇÏ°Ô µÉ °ÍÀÌ´Ù. mpeg °°Àº ¸î¹é¸Å°¡ ÆÄÀϵµ ¹«³­È÷ Àü¼ÛÇØ ÁÙ ¼ö ÀÖ¾î¾ß ÇÒÅÙµ¥ ÇöÀç ±îÁöÀÇ ÀÛ¾÷À¸·Î´Â ¹æ¹ýÀÌ ¸¶¶¥Âú´Ù. °í¹ÎÀ» Á» Çغ¸¸é,

  1. ¿©À¯¹öÆÛ»çÀÌÁî > ÆÄÀÏ»çÀÌÁî : Çѹø¿¡ ´Ù ¹Ð¾î ³Ö°í Á¾°á.
  2. 1)¿¡ ÇØ´çµÇÁö ¾ÊÀ» °æ¿ì, ÆÄÀϼ¾µåÅ¥¿¡ ³Ö°í
  3. ?OnIdle ¿¡¼­, ÆÄÀϼ¾µåÅ¥°¡ ¹«¾ð°¡ ÀÖÀ¸¸é Àü¼Û
ÀÌ ¹æ¹ýÀ¸·Î ÇÒ ¶§¿¡´Â, ÆÄÀÏ Àü¼ÛµµÁß¿¡ ´Ù¸¥ ¼¾µå¸¦ ÇÒ ¼ö ¾ø´Ù - µ¥ÀÌÅÍ ¼ø¼­°¡ ²¿Àδ٠-. ¿©·¯°³ÀÇ ÆÄÀÏÀ» ÇϳªÀÇ ¼ÒÄÏÀ¸·Î º¸³»·Á°í ÇÒ¶§¿¡µµ °³¼±µÇ¾îÁ®¾ß ÇÑ´Ù. ¾î·°Å³ª ¹®Á¦°¡ ¸¹´Ù. ÀÏ´Ü, 1)¹øÀ» ±¸ÇöÇØ º»´Ù.


Çѹø¿¡ ´Ù Àоî Àü¼Û
#define READ_ONCE  20000

int THttpClient::ResponseBody(const char *filename)
{                
    FILE *fp;    

    fp = fopen(filename, "r");
    if(fp == NULL) return -1;

    char buf[READ_ONCE];
    int  nread;      
                     
    while(!feof(fp)){
        nread = fread(buf, 1, READ_ONCE, fp);
    
        if(nread < 1) break;
        if(sendbuf->Push(nread, buf) < 1){
            // buffer overflow
            break;
        }
    }
    fclose(fp);

    return 1;
} 


1.5 EpollSocket ÀÇ ¼öÁ¤ #

±âÁ¸ ?TEpollSocket<?TEpollClient> ¿¡¼­ ÇÑ °¡Áö ¹®Á¦°¡ ÀÖ¾ú´Âµ¥, ¼­¹öÂÊÀÇ Àǵµ·Î ¿¬°áÀ» ²÷À» ¹æ¹ýÀÌ ¸¶¶¥ÂúÀº °ÍÀÌ´Ù. HTTP ÇÁ·ÎÅäÄÝÀÇ ±¸Çö¿¡¼­ ¿øÇÏ´Â ¹®¼­¸¦ ´Ù Àü¼ÛÇÏ°í ³ª¸é, ¼­¹ö´Â ¿¬°áÀ» ²÷µµ·Ï µÇ¾î ÀÖ´Ù. ¹®Á¦´Â ?SendBuffer¿¡ µ¥ÀÌÅÍ°¡ ³²¾ÆÀÖ´Â »óȲ¿¡¼­´Â ÀÌ µ¥ÀÌÅ͸¦ ´Ù Àü¼ÛÇÏ°í Á¾·áÇØ¾ß Çϴµ¥, ±âÁ¸ÀÇ ±¸Á¶¿¡¼­´Â ?OnIdle¿¡¼­ ¿¡·¯¸¦ ¸®ÅÏÇؼ­ ?TEpollSocket.Idle()¿¡¼­ Á¾·á󸮿¡ µé¾î°¡µµ·Ï ÇØÁÖ°í, º°µµÀÇ Á¾·áó¸® ÇÁ·Î½ÃÀú¸¦ ¸¸µé¾î¼­ ¹öÆÛ¸¦ ºñ¿öÁÖ°í ¹öÆÛ°¡ ´Ù ºñ¿öÁö¸é ¿¬°áÀ» Á¾·áÇϵµ·Ï ÀÛ¼ºÇØ¾ß Çß´Ù.

ÀÌ ¹®Á¦¸¦ ÇØ°áÇϱâ À§ÇØ, ?TEpollClient´Â is_readyto_close() ÇÔ¼ö¸¦ ÀÛ¼ºÇϵµ·Ï °­¿äÇÏ°í, ¹öÆÛ°¡ ºñ¿öÁ³À» °æ¿ì¿¡¸¸ true¸¦ ¸®ÅÏÇϵµ·Ï Çß´Ù (¹°·Ð read, write¿¡¼­ ¿¡·¯°¡ ¹ß»ýÇ߰ųª disconnectµÈ °æ¿ì´Â ÀÌ °æ¿ì¸¦ °Ë»çÇÒ ÇÊ¿ä°¡ ¾ø´Ù). ?TEpollSocket¿¡¼­´Â ?OnIdle¿¡¼­ °¢ ¿¬°áÀÇ is_readyto_close¸¦ °Ë»çÇؼ­, ¸¸¾à true°¡ µ¹¾Æ¿À¸é ¿¬°áÁ¾·á󸮸¦ ÇÑ´Ù (ÀÌ¹Ì ¹öÆÛ´Â ´Ù ºñ¿öÁ®ÀÖ´Ù!).

?TEpollClientÀÇ ¼öÁ¤
class TEpollClient
{
    ....
    virtual bool is_readyto_close(void) = NULL;
    ....
}; 


?TEpollSocketÀÇ ¼öÁ¤
// map <int, T *> ¶ó°í ¾²°í½ÍÁö¸¸ ¾Æ·¡Ã³·³ ½áÁà¾ß warningÀÌ ³ªÁö ¾Ê´Â´Ù.
typedef std::_Rb_tree_iterator<std::pair<const int, T*>, std::pair<const int, T*>&, std::pair<const int, T*>*> mapit;

template <typename T>
int TEpollSocket<T>::Idle(void)
{   
    mapit it = mapClient.begin();
    
    while(it != mapClient.end()){ 
        it ->second->OnIdle();
        if(it->second->is_readyto_close()) return OnDisconnect(it);

        it++;
    }
    return mapClient.size();
}

template <typename T>
int TEpollSocket<T>::OnDisconnect(mapit& it)
{
    T *tmpClient = it -> second;
    if(! tmpClient) return -1;

    mapClient.erase(it);

    epoll->Delete(it->first);
    close(it->first);
    delete tmpClient;

    return mapClient.size();
}  


?THttpClientÀÇ ¼öÁ¤
class THttpClient : public TTextClient
{
protected :
    bool is_force_close;
    ....

public :
    THttpClient(const int lfd, const char *laddr) : TTextClient(lfd, laddr)
    {
        is_force_close = false;
    };

    ....
    virtual bool is_readyto_close(void);
    ....
};

bool THttpClient::is_readyto_close(void)
{
    if(! is_force_close) return false;
    if(! sendbuf->empty()) return false;

    return true;
} 

´Ù µÆ´Ù!! ÀÌÁ¦ º¸³¾¸¸Å­ º¸³ÂÀ¸¸é, is_force_close = true·Î ÇØÁÖ¸é µÈ´Ù.

int THttpClient::msgGET(const char *url)
{
    ....

    if(...){
        ....
        ResponseHeader(httpcode, fileinfo.st_mtime, fileinfo.st_size, mime);
        ResponseBody(filename);
    }

    is_force_close = true;
    ....


1.6 Signal Çڵ鷯 #

ÇÁ·Î±×·¥ÀÌ for(;;) ÀÇ ¹«ÇÑ·çÇÁ¸¦ °è¼Ó µ¹±â¶§¹®¿¡ Á¤»óÀûÀÎ Á¾·á󸮸¦ ¸øÇÏ°í Ctrl-C ¸¦ ´­·¯¼­ ³¡³»¾ß Çϴµ¥, SIGTERM°ú SIGINT¿¡ ´ëÇÑ Çڵ鷯¸¦ ¸¸µé¾î ºÙ¿© º¸¾Ò´Ù.

=> Signal Signal Çڵ鷯

1.7 ¼Ò½º #


Replace original file
Rename if it already exist

File nameSize(byte)Date
 .. 2007-01-09
httpd1.1.tgz317552004-06-30
Total 1 files
Password:

last modified 2004-07-13 14:19:48
EditText|FindPage|DeletePage|LikePages|UploadedFiles|UploadFile|