소켓을 이용해서 HTTP을 구현시 질문

yeilho의 이미지

안녕하세요.

회사에서 필요해서 간단히 HTTP를 흉내내서 해당 파일을 웹서버에 접속해서 가져오고자 프로그램을 짜는데 이해가 되지 않는 부분이 있어서 질문 올려드립니다.

먼저 테스트 한다고 아래처럼 코드를 짜서 예를 들어 www.google.com 웹서버에 접속해서 아래 전문을 보냅니다.

  char *msg = "GET index.htm HTTP/1.1\r\n\r\n";


  if (0 > (rc = write(sd, msg, strlen(msg))) )
  {
      perror("cannot send data ");
      exit(1);
  }
  printf("%d data sent\n", rc);

  while(0 < read(sd, &ch, 1))
  {
    printf("%c", ch);
  }

그러면 결과를 아래와 같이 화면에 프린트 합니다.

Quote:

26 data sent
HTTP/1.1 400 Bad Request
Date: Thu, 07 Jul 2005 18:03:14 GMT
Server: Apache Web Server
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

17d
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>400 Bad Request</TITLE>
</HEAD><BODY>
<H1>Bad Request</H1>
Your browser sent a request that this server could not understand.<P>
client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): index
.htm<P>
<HR>
<ADDRESS>Apache/1.3.33 Server at pulsar.lunarpages.com Port 80</ADDRESS>
</BODY></HTML>

0

문제는 위에서 보시는 바와 같이 헤더와 바디사이에 17d 라는 숫자와 마지막에 0이 찍히는데 도무지 이 값이 왜생기는지 모르겠네요.

rfc 문서를 봐도 특별히 언급이 없는것 같은데.... 어쩜 저의 무식의 소치로 발견을 못했을 수도...

위의 두 숫자를 없애야 될것 같은데... 도무지 방안이 떠오르지 않아서 질문 올려드립니다.

고수님들의 의견 부탁드릴께요.

<><

소타의 이미지

http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
에서 chunked 로 찾기 해보시면 답이 나옵니다.

17d 는 16진수이고 17d 는 앞으로 전송될 데이터 양의 크기를 나타냅니다.
0 은 앞으로 전송될 데이터가 없으므로 EOF 를 의미합니다.
보통은 Content-length 라는 헤더를 통해서 클라이언트가 받을 데이터의 양을 전달하는데 CGI의 경우에는 데이터를 계속 생성해야 하기 때문에 데이터의 양을 산출하기 힘듭니다. 그래서 chunked encoding이라는 방식으로 클라이언트에게 받을 데이터의 양을 알려주는 것입니다. (꼭 CGI가 아니더라도 사용하는 경우도 있긴 합니다)

3.6.1 Chunked Transfer Coding
The chunked encoding modifies the body of a message in order to transfer it as a series of chunks, each with its own size indicator, followed by an OPTIONAL trailer containing entity-header fields. This allows dynamically produced content to be transferred along with the information necessary for the recipient to verify that it has received the full message. 

       Chunked-Body   = *chunk
                        last-chunk
                        trailer
                        CRLF
       chunk          = chunk-size [ chunk-extension ] CRLF
                        chunk-data CRLF
       chunk-size     = 1*HEX
       last-chunk     = 1*("0") [ chunk-extension ] CRLF
       chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
       chunk-ext-name = token
       chunk-ext-val  = token | quoted-string
       chunk-data     = chunk-size(OCTET)
       trailer        = *(entity-header CRLF)

keep-alive 가 지원되는 서버에서 HTTP/1.1 프로토콜 하에서는 Content-length 또는 Transfer-Encoding: chunked 두가지 중 하나는 와야 합니다. 아니면 접속을 끊어줘 버리던가..

yeilho의 이미지

:D

먼저 결과 감사합니다.

결과 내용을 파일에 담아서 사이즈를 맞추어 보니 말씀하신바 처럼 크기가 맞네요.

이제는 이 숫자들을 없앨 방법을 찾아 봐야 되는데, 일반 HTML 문서는 대충 숫자를 없앨 수 있을것 같은데...
가지고 올 데이터가 이미지나 혹은 오디오 파일인 경우에 좋은 의견 있으시면 부탁드릴께요.

다시 한번 감사드립니다.

<><

Linux rules!!!

acidd15의 이미지

Transfer-Encoding: chunked

청크엔코딩 되었음을 의미합니다.

Quote:

17d

16진수 형태로 되어 있는 chunk size 입니다. 이 chunk size는 여러번 출현할수도 있습니다.즉

Quote:

[chunksize1]
chunk1
[chunksize2]
chunk2
[chunksize3]
chunk3
[chunksizeN]
chunkN
0

맨 마지막의 0도 chunk 입니다.0은 앞으로 더 이상 읽을 chunk가 없음을 의미 합니다.사실상 contents의 마지막임을 알리는 겁니다.

chunk 엔코딩을 하는 이유는 contents가 정확히 도착했는지를 판단하는 수단으로 사용하기 위해서 입니다.

즉 님 말씀처럼 청크 사이즈를 개별적으로 지운다는건 데이터 무결서을 훼손하는 상당히 비효율적인 방법이구요.

일단 헤더와 바디를 분리한다음.바디의 맨 처음 부분에서 맨처음 chunksize1 을 추출하시고 하면서...

연결리스트를 만들어서 청크사이즈를 발견할때마다 chunk노드를 추가시킨다음 chunk 노드들을 merging하면 하나의 완벽한 contents가 되겠지요..

화장실이 급하군요 -- :oops:

익명 사용자의 이미지

저도 같은 경험을 했습니다..

저는
<?ob_start();?>

HTML...
..
..
<?
$ob_conent = ob_get_content();
header( 'Content-Length:' . strlen($ob_content) );
ob_end_flush();
?>

이렇게 하면 Transfer-Encoding: chunked형태로 넘어오지 않더군요...
함수들이 정확하게 적었는지 모르겠네요... 그럼 수고...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.