소켓 통신에서...

하하의 이미지

소켓 통신 중 .. 연결하려는 호스트까지 네트워크 병목현상이 있어

어느 정도(3초~5초)의 delay time 후 connect이 확립됩니다.

그럴때... 호스트로 부터 recv를 할려 하면 아래와 같이 구현해보면

            while ( hdsz > recv_total ) {

                recv_byte  = recv(sock, header + recv_total, hdsz - recv_total, 0);

                recv_total = recv_total + recv_byte;


                if ( hdsz > recv_total ) {
                        if (cnt > 5)  break;
                        else {
                                      cnt++;
                                      sleep(5);
                        }

                        printf("*****received byte %d , total %d\n", recv_byte, recv_total);
                }
            }

메세지를 다 받지 못하였을 때 5초후 recv를 다시 시도 하게끔

구현 하였습니다.

헌데 이럴 경우 5초식 5번 recv를 시도 하여도 한 byte도 받지 못하고

0, 0, 0, 0, 0 byte만을 받다가 끝나고 맘니다.

그런데 이상한건..

            sleep(5);

            recv_total = recv(sock, header, hdsz, 0);

이런식으로 최초 recv하기도 전에 5초간 쉬고.. recv를 하면 100% 데이터를

받아 온다는 겁니다.

한번의 실패도 없이요........

제가 못 보는 다른 문제가 있는건지요?

조언 부탁드립니다.....

아 .. 그리고 위와 같이 데이터를 못받았을때 위와 같이 sleep을 주는 게

일반적인 방법인지도 알고 싶습니다.

liongo의 이미지

안녕하세요.. 질문만 보아서는 약간 자료가 부족하나..

제가 아는한도에서 이야기를 하도록 하겠습니다.

네트웍이 느려서 recv를 한경우 timeout 시간이 초과되면

데이타를 받지 못하고 리턴되는경우가 잇습니다. 또한 논블러킹인

경우에도 그렇죠. 그리고 sleep는 일반적으로 사용하지 않습니다..

특수한경우빼고는요.. 고로 소켓관련 이벤트 처리를 해주셔야할것같습니다.

소켓의 시간초과 예외나 또는 누군가 한번보낸다고 꼭 한번 recv해서

처리되지 않는경우도 있씁니다. 그리고 몇몇예외가 있지요..

그런것을 기본적으로 감안하시면 되실것 같습니다.

결론 sleep을 안써도 된다.~ -_-!

언제나 제가쓰는글은 잡설같군요..

' 형식이 내용을 규정한다. '

ifyou의 이미지

논블러킹으로 구현하신거 맞으신가요?

connect하는데 3~5초가 걸린다는게 믿어지지는 않지만

그렇다고 하니 어쩔 수 없고....

말씀하신 상황과 코드만 가지고는 납득이 안 가는 부분이 너무 많지만, 많은 경우의

수와 가능성을 고려해 볼때..


while ( hdsz > recv_total ) { 

                recv_byte  = recv(sock, header + recv_total, hdsz - recv_total, 0); 

                recv_total = recv_total + recv_byte; 


                if ( hdsz > recv_total ) { 
                                      cnt++; 
                                      sleep(5); 
                                      if (cnt > 5)  break;  
                        } 

                        printf("*****received byte %d , total %d\n", recv_byte, recv_total); 
                } 
            } 
 

요렇게 해 보면 되지 안을까 싶습니다.

그리고, 일반적으로 sleep() 사용하지는 않지요. 논블러킹에서 recv()쓸때는 select()와 많이 조합해서 씁니다.

http://doc.kldp.org/Translations/html/Socket_Programming-KLDP/Socket_Programming-KLDP.html

.

서지훈의 이미지

select() 가 제가 보기에도 가장 나을거 같네요...
sleep()을 사용한다는건 꽁수 같구요^^
select()는 sleep()의 기능도 하면서 일정한 시간동안 계속 잠들어 있는게 아니라...
데이타가 들어오면 바로 깨어나서 자료 송/수신을 하니 sleep() 보다 나을거 같군요.

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

danielkim의 이미지

select를 사용하세요

현상을보니 nonblocking 모드로 되어 있어신것 같습니다.

select를 이용해서

int is_rxsocket_ready(int socket , int timeoutsec, int usec);
이라는 함수를 하나 만드시고

      
 if ( is_rxsocket_ready(rx_socket, tosec, tousec) > 0 ) {
                 //  read_socket (rx_socket.....
       } else {
             // No data availble .... 

       }

이런식으로 처리하시면 time out 만큼 기다리는게 아니라
timeout 이전이라도 data가 들어오면 처리를 하게 됩니다.
socket은 nonblocking 모드로 설정되어야 겠죠.
파이팅 하세요
하하의 이미지

recv 받는 루틴은 아래와 같이 구성되어 있습니다.

주석으로 막은 부분은 위에서 설명한 바대로 0 byte 만을 루프를

돌면서 받고 끝내 실패...

            sleep(5);

            recv_total = recv(sock, header, hdsz, 0);

요런식의 꽁수를 써서 recv를 해보면 그재야 데이터를 받을 수 있습니다.

sock은 블럭킹 모드 입니다.

저도 하도 이상하길래.. 아래와 같이 sleep을 주어 delay 타임을 준

것이구요.. sleep(5) 이하 그러니깐 sleep(4) 이하를 주면 역시 0

byte 만을 받습니다........

            FD_ZERO(&mask);
            FD_SET(sock, &mask);
            timeout.tv_sec  = configi(config, RECV_TIMEOUT);
            timeout.tv_usec = 0;


            if ((r = select(sock + 1, &mask, NULL, NULL, &timeout)) == 0 ) {
                TRACE(_EVENT,"recv timeout error occure reason=[%s] connfd=[%d]\n", strerror(errno), sock);
                goto L0;
            }

            if (r < 0) {
                TRACE(_EVENT,"read select error occure reason=[%s] connfd=[%d]\n", strerror(errno), sock);
                goto L0;
            }


            sleep(5);

            recv_total = recv(sock, header, hdsz, 0);


/*
            while ( hdsz > recv_total ) {

                recv_byte  = recv(sock, header + recv_total, hdsz - recv_total, 0);

                recv_total = recv_total + recv_byte;


                if ( hdsz > recv_total ) {
                        if (cnt > 5)  break;
                        else {
                                      cnt++;
                                      sleep(5);
                        }

                        TRACE(_EVENT, "*****received byte %d , total %d\n", recv_byte, recv_total);
                }
            }
*/
            TRACE(_EVENT, "received data %d\n", recv_total);


            if ( recv_total <= 0 ) {
                TRACE(_EVENT,"receive data (0 byte) reason=[%s] connfd=[%d]\n", strerror(errno), sock);
                goto L0;
            }

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

하하의 이미지

Quote:

while ( hdsz > recv_total ) {

recv_byte = recv(sock, header + recv_total, hdsz - recv_total, 0);

recv_total = recv_total + recv_byte;

if ( hdsz > recv_total ) {
cnt++;
sleep(5);
if (cnt > 5) break;
}

printf("*****received byte %d , total %d\n", recv_byte, recv_total);
}
}

이처럼 recv를 하고 sleep(5)를 주어도 마찬가지로 0 byte만을 반복적으로

받습니다..

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

지리즈의 이미지

하하 wrote:
소켓 통신 중 .. 연결하려는 호스트까지 네트워크 병목현상이 있어

어느 정도(3초~5초)의 delay time 후 connect이 확립됩니다.

이 병목 현상의 원인은 거의 대부분 name resolving입니다.

x=foo(y)가 성립되지 않는 세계에 오신걸 환영합니다.

There is no spoon. Neo from the Matrix 1999.

댓글 달기

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