소켓에서 recv를 하는것과 관계가 잇는지..?

lkjt의 이미지

	for(i=0;;i++)
	{
		if(i==1)
			Sleep(1000);
		RecvBytes = recv(m_sock, recvbuf, sizeof(recvbuf)-1, 0);
		recvbuf[RecvBytes] = NULL;		
		htmlsource += recvbuf;		
		out<<recvbuf<<endl;
		if(RecvBytes != sizeof(recvbuf)-1)
			break;
	}

소스코드를 이렇게 짯는데요 .

이렇게 하면 잘됩니다.

그런데 저기 Sleep을 빼면 중간에 출력이 되다가 마는데요.

왜그러는지.. 또, 어떻게 해야 고칠수 있나요?

lovemyin의 이미지

일단 님이 올리신 질문의 요점에 맞는지 확실하지는 않지만
제가 보기엔 님이 말하시는 말은 Sleep을 넣으면 출력이 제대로 되는데
Sleep이 없으면 출력이 되다가 만다는 말씀으로 알아듣겠습니다.
제가 보기엔 되다가 마는게 아니라 Sleep을 빼면 recv 타임이 너무 빨리 돌아오기때문에 님이 원하시는 데이터가 전부 도착하기 전에 recv가 호출되는 것 같습니다.
그래서 출력내용이 잘린다고 느끼시는거구요...

/***************************************************
* 가장 심플한 것이 가장 아름다운 것이다.
***************************************************/

jinyeong의 이미지

      if(RecvBytes != sizeof(recvbuf)-1) 
         break; 

이걸 지워 보시면 어떨까요?

I thought what I'd do was,
I'd pretend I was one of those deaf-mutes.. or should I?

mach의 이미지

<잡담>
* 제 신조 중에 하나가 "질문을 위한 질문에 답변을 위한 답변은 안한다." 입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

bugiii의 이미지

Sleep 하지 않으면 동작하지 않는다라고 했으니 아마 해당 소켓이 넌블럭이나 타임아웃이 걸려있다고 보이구요. (블러킹이라면, 1혹인 몇바이트만 받은 상태) 하여튼, recv 류의 리턴값을 조사하지 않는 것 부터가 잘못 작성된 코드입니다.

이 질문은 recv 가 리턴되는 경우가 어떤 것이 있는지 알면 저절로 풀리는 문제라고 봅니다. 어떤 경우가 있는지 확실하게 알아보시기 바랍니다. 리턴되고 나서 에러일 경우 어떻게 처리해야 하는지도 확실하게 해야 합니다.

보시는 책에 recv 가 어떨 때 리턴되는지 나와있지 않나요? 그 책 버리십시오. man 이 없나요? msdn 이 없나요? 마음이 급해도 읽어야 할 것은 읽어야 하고 이해할 것은 이해해야 합니다.

p.s. 냉정하게 들릴지 모르지만, 책 몇권, 다른 사람 코드 좀 보고 이렇게 저렇게 해보겠다는 생각은 당장 그만두시기 바랍니다. 아마 이런식의 질문에는 계속 이런 답변 밖에는 달릴 수 없을 것 같습니다.

lkjt의 이미지

한줄씩 디버깅을 해보면 에러 코드 리턴은 안하는데요.

그리고 RecvBytes 가 sizeof(recvbuf)-1이랑 같지 않으면 break;한건

리턴이 < 0이면 break하게 해놓으니 속도가 느려지더군요.

그러니까 1499가 리턴 되면 빠르게 되는데 .

-1을 기다린는건 recv함수에서 1분 정도 걸리더군요..

bugiii의 이미지

누가 에러 코드라고 했습니까? 저는 분명히 어떨 때 리턴되는지를 알아보라고 말씀드렸습니다.

ㅡ,.ㅡ;;의 이미지

아마도 제예상에 sleep 이 없으면 서버쪽send buf 의 크기만큼 출력후 빠져나가겠네요..

그문제는 데이터의 흐름보다 처리가 빨라서 발생하는문제(?) 입니다.

사실 문제를 님이 만드셨네요..^^ 때문에..탈출하는것이 아니라 작은조각들을

모으는작업을 하여 하나의 패킷으로 완성해서 넘겨주곤하죠..


----------------------------------------------------------------------------

sharefeel의 이미지

한번의 send가 여러번의 recv로 쪼개져서 들어올 수 있습니다.
즉 다음과 같은 상황이 있을 수 있습니다.

send(buff, 10000)
하더라도
n = recv(buff, 10000);
의 n<10000일 수 있습니다.

만약 그런 경우라면그 경우에는

if(RecvBytes != sizeof(recvbuf)-1)
         break; 

에서 break가 걸려 루프를 탈출하고 모든 데이터를 수신하지 못하게 됩니다.
이런 경우 루프를 돌며 recv를 데이터를 다 받을 때까지 호출해줘야겠지요..

혹은 recv(...., MSG_WAITALL);
옵션을 통해서 데이터를 전부 모아서 받을 수도 있습니다만...
저 옵션이 리눅스에는 있는데 솔라리스나 윈도에는 또 없더군요..

===============
Vas Rel Por

lkjt의 이미지

헉,, WSAGetLastError()

connection lost by peer

서버 에 의해서 끊겻다네요 -.-;;

파일이 다 받아지고 서 끊기는데...이거 어떻게 해야 막아질가요 ㅠㅠ

Keep-Alive를 해도 마찬가지내요 ㅠㅠ

ps.

다른 서버는 잘 됫는데 여기가 안됫던게
서버가 끊어서 그런거엿군요...
그런데 어떻게 해야 막을지 ㅠㅠ

bugiii의 이미지

다 받을 때까지는 특별한 일이 없는 한 접속 유지 됩니다. 다 받고 나서 접속 유지는 옵션을 주든 안주든 웹 서버 마음입니다. 항상 대비해야 합니다. 1.1 로 보냈다고 1.0 지원하는 서버가 1.1 방식대로 동작하리라고 생각한다면 큰 잘못입니다.

웹은 기본적으로는 하나의 페이지가 완성되면 접속을 서버측에서 끊는 것입니다. 만약 옵션이 접속유지 요청을 하고 서버도 이것을 접수해서 연결되어 있다면 다음번의 요청은 접속 요구없이 그냥 요청하면 됩니다. 하지만 끊겼으면 다시 접속하면 되는 것 아닙니까?

윗글에서는 에러 없다고 하고, 밑에는 다시 에러라고 하고... 왔다갔다 하지 마십시오.

질문한 것에 대해 답변자들이 답변을 하고 그것에 따라서 어떻게 되었다라거나 혼자서 변경를 어떻게 해서 잘 되더라 는 정도는 올리고 나서 다음 질문을 하시면 좋겠습니다.

그러니까, 지금까지의 요청한 페이지 데이타를 어찌어찌 해서 다 받기는 했는데 (이전의 질문에 대한 답변으로 어느정도 해결했다고 추측), 이제 더 해볼려니까 접속이 끊겨서 다시 접속을 해야 하더라 (두번째 질문이라고 추측). 어떻하면 좋을까요? 어떤 곳은 접속없이 다시 요청해도 되던데, 이상하더라. 이렇게 질문하려고 하신 겁니까?

중간과정 생략하는 것도 글 보시는 분들에게 많은 부담이 됩니다.

p.s. 완곡한 표현을 찾기가 무척 힘들어지고 있습니다.

ㅡ,.ㅡ;;의 이미지

lkjt wrote:
헉,, WSAGetLastError()

connection lost by peer

서버 에 의해서 끊겻다네요 -.-;;

파일이 다 받아지고 서 끊기는데...이거 어떻게 해야 막아질가요 ㅠㅠ

Keep-Alive를 해도 마찬가지내요 ㅠㅠ

ps.

다른 서버는 잘 됫는데 여기가 안됫던게
서버가 끊어서 그런거엿군요...
그런데 어떻게 해야 막을지 ㅠㅠ

그런문제가 종종 있을수 있습니다.. 물론 해결책도 있겠죠..
이런문제는 잘하면 쉽게 해결되는거 같군요....
그러니까 벌써 님이 이미 원인도 알고계시고 있네요....
그서버도 다른서버랑 똑같이 하면 되는거 아닌가요....


----------------------------------------------------------------------------

lkjt의 이미지

다른서버는 잘됩니다.

그런데 유난히 그서버만 recv를 다하고 나서는 recv()가 1분정도 걸리더군요.
기다리다가 타임아웃이 되는거 같은데요...

그래서 이렇게 해결을 해볼까 하는데요..

헤더에 보면 콘텐츠 길이가 나오는데 그만큼 받으면 저절로 루프를 탈출.

하게 하려고요. 괜찮은 방법인가요?

lkjt의 이미지

	char		recvbuf[32];
	size_t	ContentsLength;
	int		LengthBegin;
	int		HeaderEnd;
	bool	Finded = false;
	SOCKET		m_sock;
	int		bytesRecv;

	while(1)
	{
		bytesRecv = recv( m_sock, recvbuf, sizeof(recvbuf)-1, 0 );
		recvbuf[bytesRecv] = NULL;		
		htmlsource += recvbuf;		

		if(Finded == true)
		{
			if(htmlsource.length() >= ContentsLength)
				break;
			else
				continue;
		}

		if((LengthBegin = htmlsource.find("Content-Length: "))) //  < htmlsource.length()
		{
			LengthBegin += strlen("Content-Length: ");
			ContentsLength = atoi(htmlsource.substr(LengthBegin, htmlsource.find("\r\n", LengthBegin) - LengthBegin).c_str());
			HeaderEnd = htmlsource.find("\r\n\r\n", LengthBegin) + strlen("\r\n\r\n");
			if(HeaderEnd == 3)
				continue;
			htmlsource = htmlsource.substr(HeaderEnd);
			Finded = true;
		}
	}
ㅡ,.ㅡ;;의 이미지

lkjt wrote:
다른서버는 잘됩니다.

그런데 유난히 그서버만 recv를 다하고 나서는 recv()가 1분정도 걸리더군요.
기다리다가 타임아웃이 되는거 같은데요...

그래서 이렇게 해결을 해볼까 하는데요..

헤더에 보면 콘텐츠 길이가 나오는데 그만큼 받으면 저절로 루프를 탈출.

하게 하려고요. 괜찮은 방법인가요?


별로 안좋은게 아닐까... 하는...


----------------------------------------------------------------------------

lkjt의 이미지

왜 별로 안좋은거죠...?

feanor의 이미지

여러분, lkjt님께 답변하지 맙시다. 답변하는 것이 전혀 lkjt님에게 도움이 되지 않는다고 생각합니다.

--feanor

bugiii의 이미지

feanor wrote:
여러분, lkjt님께 답변하지 맙시다. 답변하는 것이 전혀 lkjt님에게 도움이 되지 않는다고 생각합니다.

--feanor

결국은 이런 얘기까지 나오는군요... 안타까울 따름입니다.

댓글 달기

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