소켓 프로그래밍 첨하는데 버퍼링같은걸 어떻게 구현할지 모르겠습니다 ㅠㅠ

jonyon의 이미지

안녕하세요. 맨날 눈팅만 하다가 처음으로 가입해서 포럼주제 써봅니다.

KLDP 위키의 BeeJNetworkProgramming 문서 보면서 소켓 프로그래밍 공부하고 있습니다.
번역해주신분께 너무나 감사할 따름입니다 ㅎㅎ

제가 만들고 있는 프로그램은
i)사용자로부터 URI를 받아서
ii)해당하는 HTML문서를 네트워크에서 받아오고
iii)그 문서를 파일로 저장하는
프로그램입니다.

우선 i)번 과정은 대부분 된것 같은데, ii)번 과정이 문제입니다.
프로그래밍 연습할때는 끽해야 자료 크기가 바이트단위에서 노는데, 인터넷에 돌아다니는 html문서는 1KB가 넘는 경우가 많습니다 ㅠㅠ
이 커다란 자료를 받아오려고 두가지 방법을 생각해 봤는데,
1. 엄청나게 커다란 변수를 만든다!
2. 조금씩 받아와서 합친다!
아무래도 1번은 좀 아닌것 같고, 2번 방법을 써야될것 같더라구요.

조금씩 받아오는걸 어떻게 하면 좋을까요?
문서를 보면 recv()함수 인자를 통해 받아올 최대 사이즈를 정할수 있다고 하는데, 그렇게 사이즈를 정해놓으면 (예를 들어 256바이트라 했을때) html문서 맨앞의 256바이트밖에 안받아옵니다.
그 이상을 계속해서 받아오는 방법을 모르겠어요.

kldp분들께 욕을 얻어먹지 않기 위해 구글 검색도 해보았지만, C에서 구현된 http라이브러리 소개글만 죽죽 읽다가 허탕쳤습니다...

아무래도 이걸 버퍼링이라고 부르는 모양인데, 버퍼링을 어떻게 구현해야 하나요? (버퍼링이 아닐 수도 있습니다. 버퍼링이란 용어는 그냥 무시해주세요.)

소스는 별 도움이 될것같지 않아서 (send나 recv하는 코드가 아예 없습니다. 서버에 connect하는 부분까지만 만들었어요) 올리지 않기로 했습니다.

구구절절 하소연 비슷한 질문글 읽어주셔서 감사합니다.

barunjo의 이미지

안녕하세요 저도 눈팅만하다가 님이 쓰신글을 보고 글을 적어봅니다.
BeeJNetworkProgramming 자료 공유가 가능하신지요? 함께 연구해보고 싶네요.

yhsuk의 이미지

Signature :) - "여유를 갖고 행동하되 게을러지지 말자"

익명 사용자의 이미지

recv으로 256바이트를 읽은 다음에 recv를 한 번 더 호출하면 그 다음 부분부터 받을 수 있습니다. 받을 게 남아 있다면 말이죠. 직접 여러 번 호출해서 받은 데이터를 출력해보세요.
(받을 게 남아있지 않은데 recv를 호출하면, 소켓 속성에 따라 다르긴 하지만 블록당할 수도 있으니 주의가 조금 필요합니다.)

jonyon의 이미지

말씀하신대로 원하는만큼 들어올때까지 recv()하는 방식으로 해결했어요. 소켓 블록은 한번 공부해봐야겠네요.

BrownBear의 이미지

https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms740121(v=vs.85).aspx

Return value

If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.

Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

정확히 MSDN에 설명되어 있습니다.

오류가 발생하지 않았다면 recv는 수신된 수의 크기를 반환할 것이고 버퍼 포인터는 수신된 데이터가 들어있을것이다

만약 연결이 끊겼다면(더 이상 받을 데이터가 없다면 이라고 해석하시면 되겠네요) 0을 반환할것이다.

그 외의 SOCKET_ERROR을 반환했거나 그리고 다른 오류 코드들은 WSAGetLastError을 통해 가져올 수 있을것이다.

그냥 간단하게

do
{
 //수신된 데이터를 지지고 볶고
}
while(recv(s, buf, len, flags) > 0); 

으로 하셔서 받으시면 안되나요? SOCKET_ERROR도 검사하는 루틴 포함시켜서.

정확히 사용해보지 않아서 모르겠지만 위와 같은 방법으로 0이 클때까지 돌리시면 될건데요

0이면 받을 데이터가 없는거고 음수면 오류가 뜬거니깐 WSAGetLastError을 사용하셔서 적절히 대응하시면 될것같고

정확히 밑의 예제에 구현이 되있네요.

 do {
 
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
 
    } while( iResult > 0 );

아마 검색해보시면 가장 효율적으로 데이터를 송수신할 수 있는 크기가 어디 나와있을겁니다.

https://en.wikipedia.org/wiki/TCP_tuning

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=59261&ref=59253

http://egloos.zum.com/psjHello/v/103770

뭐 그냥 전송할 크기를 참고해 입맛에 따라 구현하시는게 맞을거라 봅니다.

jonyon의 이미지

대충 256바이트 정도로 해서 데이터 받았어요.
윈도랑 리눅스랑 소켓함수는 많이 비슷하네요. 감사합니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.