CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    May 2018
    Posts
    158

    right management of recv function in C

    I'd like to know if return code test of recv function in my C application, according to std c89, is right.

    Code:
    While (1) {
        ...
        ret = recv(socket, buffer, lun, 0);
    
        if ( ret == -1 || ret != lun ) {
                perror("error during data receive");
                continue;
        }
        if ( ret == 0 ) {
                perror("remote socket was been closed");
                close(socket);
        }
       ...
     }

    Suppose I need to receive data from client and this one is a partial code of server, where lun is exactly dimension of data which I want to receive.
    I'll check result as zero, when remote socket of client has been closed, so I have to close the corresponding socket on server side.
    I'll check -1 result, that is general error condition that perror will show but I give other chances to client to send data.
    I have doubt about ret!=lun, because in code examples someone simply tests (if ret > 0) as good condition without to test (ret == lun).
    I think : I'm waiting lun bytes because I have to test ret>0 ? What It can be reason ?
    What do you think my code ?

  2. #2
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,800

    Re: right management of recv function in C

    From MS documentation:

    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.
    .

    https://learn.microsoft.com/en-us/wi...f-winsock-recv

    So for an error you should test ret against SOCKET_ERROR and not -1 (even though SOCKET_ERROR is probably -1). This should be the first test.

    A value of 0 is returned if the connection has been gracefully closed - so this should be the second test.

    Any other ret value is the number of bytes received. This may or may not be the number expected eg less may be received than expected. So something like this:

    Code:
    ret = recv(socket, buffer, lun, 0);
    
    if (ret == SOCKET_ERROR)  {
        perror("error during data receive");
        // Terminate any processing here
    }
    
    if ( ret == 0 ) {
        perror("remote socket was been closed");
        close(socket);
        // Terminate processing
    }
    
    if (ret != lun ) {
        perror("Incomplete data received");
        // Deal with missing data. This is NOT an error
        continue;
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Nov 2018
    Posts
    95

    Re: right management of recv function in C

    Is your socket TCP (aka stream) or UDP (aka datagram)?

    Let's assume a stream.

    You should do this
    Code:
    total = 0;
    while ( total != lun ) {
        ret = recv(socket, buffer + total, lun - total, 0);
        if ( ret == 0 ) {
            // closed
            break;
        }
        if ( ret == -1 ) {
            // error
            break;
        }
        total += ret;
    }
    
    // check whether you got the whole buffer and
    // handle accordingly.

    The same applies to send() as well.
    Don't assume that a single send() call will send the entire buffer in one call.

    Message fragmentation on both send and recv are your concern and need to code accordingly.

  4. #4
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by salem_c View Post
    Is your socket TCP (aka stream) or UDP (aka datagram)?
    TCP

    How you suggested, It likes there is limit to send bytes in a single task ? What is maximum size of buffer to receive / send data at one time ?

  5. #5
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,800

    Re: right management of recv function in C

    What is maximum size of buffer to receive / send data at one time ?
    Have a look at:
    https://stackoverflow.com/questions/...socket-library
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Nov 2018
    Posts
    95

    Re: right management of recv function in C

    Well I wouldn't expect say trying to send 1MB in a single send() call to just work for example.

    Quote Originally Posted by man pages
    If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
    The smallest amount that I might expect to be sent in a single send() call might be the MTU size - under ideal conditions.
    https://en.wikipedia.org/wiki/Maximum_transmission_unit

    But conditions are seldom ever ideal.
    https://en.wikipedia.org/wiki/Fallac...uted_computing

    If you're dealing with send() and recv(), you're pretty much at the transport layer in https://en.wikipedia.org/wiki/OSI_model
    Your application might try to send "ABCD", but you need to be able to cope with the fact that send() might only transmit "ABC" on the first call, and you need to loop to send "D".
    Similarly on the recv() side, you might get "AB" followed by "CD".

  7. #7
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by 2kaud View Post
    Let's suppose programmer doesn't know buffer size and It's need to send 8192 Bytes, how programmer should have to set cycle to send data by TCP socket ? I think by multiple blocks of data sending... but what maximum size (bytes) has to be for a single sending ?
    Are there rules or best practise about this behaviour?
    It likes a jump to empty place!

  8. #8
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by 2kaud View Post
    My environment is Ubuntu OS and compiler is gcc

  9. #9
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by 2kaud View Post
    So for an error you should test ret against SOCKET_ERROR and not -1 (even though SOCKET_ERROR is probably -1). This should be the first test.
    if you run man recv in return value section says:

    On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set to indicate the error

  10. #10
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by salem_c View Post
    Your application might try to send "ABCD", but you need to be able to cope with the fact that send() might only transmit "ABC" on the first call, and you need to loop to send "D".
    Similarly on the recv() side, you might get "AB" followed by "CD".
    But this behaviour depends of how application Is made, according to your example programmer decides how to send data:
    programmer can decide to send "AB"or "ABC" on 1st SEND , so RECV will receive "AB" or "ABC" on 1st stage and on 2nd stage "CD" or "D".

    programmer will decide it , right ?

  11. #11
    Join Date
    Nov 2018
    Posts
    95

    Re: right management of recv function in C

    > programmer can decide to send "AB"or "ABC" on 1st SEND
    No, the programmer tries to send "ABCD" in a single send call, and hopes that a single recv call at the other end will get "ABCD".

    The reality is not necessarily the case.
    Code:
    int mySend(int sock, const char *buff, size_t len) {
      while ( len != 0 ) {
        ssize_t r = send(sock, buff, len, 0);
        if ( r > 0 ) {
          // we sent at least one byte, possibly all of them
          size_t sent = (size_t)r;
          buff += sent;  // skip over the part of the buffer already sent
          len -= sent;   // reduce the amount left to send
        } else {
          // handle r == 0 and r == -1 cases
          // and break from the loop
        }
      }
      return 0;
    }
    
    /// elsewhere
    if ( mySend(sock,"ABCD",4) == 0 ) {
      // success
    }
    Ordinarily, you might expect send() to send all 4 bytes in a single call, and the while loop executes exactly once.
    Or for some reason, it calls send() several times with some combination of sub-strings of "ABCD" such as "ABC" then "D".

    Either way, it makes no difference to the caller, "ABCD" is now on it's way to the other end of the connection.

    And at the other end
    Code:
    int myRecv(int sock, char *buff, size_t len) {
      while ( len != 0 ) {
        ssize_t r = recv(sock, buff, len, 0);
        if ( r > 0 ) {
          // we got at least one byte, possibly all of them
          size_t got = (size_t)r;
          buff += got;  // skip over the part of the buffer already got
          len -= got;   // reduce the amount left to get
        } else {
          // handle r == 0 and r == -1 cases
          // and break from the loop
        }
      }
      return 0;
    }
    
    /// elsewhere
    char buff[4];
    if ( myRecv(sock,buff,4) == 0 ) {
      // success
    }
    The point is, both send() and recv() need loops around them to deal with the case when r != len on the first call.

    But the number of actual calls to send() has nothing to do with the resulting number of calls to recv() for any given sequence of bytes.

  12. #12
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,800

    Re: right management of recv function in C

    if you run man recv in return value section says:
    The links I posted refer to MS Windows and Visual Studio - which is what I only use.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  13. #13
    Join Date
    May 2018
    Posts
    158

    Re: right management of recv function in C

    Quote Originally Posted by salem_c View Post
    Ordinarily, you might expect send() to send all 4 bytes in a single call, and the while loop executes exactly once.
    Or for some reason, it calls send() several times with some combination of sub-strings of "ABCD" such as "ABC" then "D".
    It's very interesting what you are saying: for some reason, it calls send() several times
    so It's possible for few byte for some reason bytes can to be sent/recevived in multiple call so It's always necessary to use loop to make sure all data has been sent/received, right ?

  14. #14
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,800

    Re: right management of recv function in C

    Quote Originally Posted by zio_mangrovia View Post
    It's very interesting what you are saying: for some reason, it calls send() several times
    so It's possible for few byte for some reason bytes can to be sent/recevived in multiple call so It's always necessary to use loop to make sure all data has been sent/received, right ?
    Yes.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured