얼마전에 간단한 서버/클라이언트 프로그램을 만든적이 있다. 어떤 놈이 나에게 못 미더운 듯이 묻기를 왜 recv를 처리하는 곳에는 while을 이용해서 read operation에 대한 오류 처리를 해주는데 send에 대해서는 아무런 처리를 하지 않냐고 했다.

블록킹 소켓일 경우 send 함수는 지정된 바이트를 모두 전송하기 전까진 리턴을 하지 않기 때문에 괜찮다라는 이야기를 친절(?)하게 해주었지만 이 샹콤한 놈의 자식이 아니라고 바득 바득 우기는데야...결국에 실험으로 보여주기는 너무 귀찮아져 man page를 찾아 보여주는 수고까지 해야 했다.

When the message does not fit into the send buffer of the socket, send normally blocks, unless the socket has been placed in non-blocking I/O mode. 
위의 내용을 간단하게 이야기 하자면 blocking 소켓에다가 send 버퍼를 넘어가는 데이터를 전송하라고 요청하면 블록킹 된다는 것이다. 다만 non-blocking 소켓은 EAGAIN 에러를 떨어 뜨린다는 것이다(여기서 우리는 non-blocking 모드에서는 errno를 철저하게 점검해야 하는 필요성을 느낄 수 있다).

한동안 포스팅 안하다가 포스팅이 이런 것이라니...혹시나 또 모르는 사람이 있을까 싶어서 적어 본다.

오늘의 교훈 : 우기지 말것(너 뿐만 아니라 나도-_-;;).
Posted by kukuta
TAG

댓글을 달아 주세요

  1. 천재 2009.01.09 18:19  댓글주소  수정/삭제  댓글쓰기

    기억은 정확히 나지 않지만 EINTR 이 온 경우 재시도 하기도 함.
    못 미더운 녀석

  2. Favicon of https://www.ikpil.com BlogIcon 최익필 2009.01.26 04:55 신고  댓글주소  수정/삭제  댓글쓰기

    http://msdn.microsoft.com/en-us/library/ms740149(VS.85).aspx 의 설명을 보면, "If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter" 이렇게 되어 있는데, 혹시 리눅스 계열은 다른가요?

    ... 이거 도통 모르겠네요;

    • Favicon of http://kukuta.tistory.com BlogIcon kukuta 2009.01.26 15:51  댓글주소  수정/삭제

      후움...알아 보고 연락 드리도록 합죠. 요것도 하나의 포스팅이 될 수 있겠는 걸요?

    • Favicon of http://kukuta.tistory.com BlogIcon kukuta 2009.01.26 15:56  댓글주소  수정/삭제

      동일한 페이지를 읽다 보니 아래와 같은 말도 있네요..
      "If no buffer space is available ..., send will block unless the socket has been placed in nonblocking mode..."
      라고 되어 있는데요. 아마도 위에서 익필님이 말씀하신 것은 blocking, non-blocking을 모두 통털어서 이야기 하는 것 같네요.

  3. Favicon of https://rhea1st.tistory.com BlogIcon Rhea Strike 2009.01.29 15:23 신고  댓글주소  수정/삭제  댓글쓰기

    암튼 동기소켓도 보낼때 Send()의 리턴값 구해 뺑뺑이 돌려주는게 정석... .

  4. Favicon of http://azena.info BlogIcon azena 2009.02.06 15:01  댓글주소  수정/삭제  댓글쓰기

    send() 함수에서 전송이 완료되는 시점까지 블럭킹 걸리는 것은 사실입니다만
    무한대로 전송을 기다리지는 않습니다.

    setsockopt 에서 지정할 수 있는 SO_SNDTIMEO 까지 기다리게 되는데
    문제는 타임아웃이 되어서 리턴이 되어도 리턴값은 보낸 바이트 수가 됩니다.

    즉, 100 바이트를 보내라고 시켰는데, 네트워크가 너무 느려서 50 바이트 밖에 못 보냈는데
    TIMEOUT이 되어서 리턴을 하면, 리턴값은 에러가 아니라 50 이라는 이야기죠.

    이것을 처리해주지 않으면 나머지 50 바이트는 안드로메다로...

    즉, 샹콤한 놈의 자식님의 말이 맞습니다. ㅎㅎ
    그동안 에러가 없이 동작한 이유는 타임아웃 동안 데이터를 다 못 보낼만큼 큰 데이터를 보낸 적이 없거나 네트워크 상태가 좋았기 때문입니다. 기본 타임아웃 시간이 긴 것도 한 몫하죠.

    • Favicon of http://kukuta.tistory.com BlogIcon kukuta 2009.02.06 17:32  댓글주소  수정/삭제

      오...넹!!
      우기지 않겠습니다. 샹콤한 놈의 자식한데 알려줘야 겠네요.

      알려주셔서 감사합니다.

  5. mhpark 2009.10.20 19:17  댓글주소  수정/삭제  댓글쓰기

    blocking은 영원히 blocking은 아니지만 #define LONG_MAX ((long)(~0UL>>1)) 시간만큼 기다리게 됩니다.

    2147483647초이지요. 물론 시그널에 의한 EINTR발생시에는 리턴하게 되지만요.

  6. 2010.07.25 10:03  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다