-
July 13th, 2023, 10:18 AM
#1
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 ?
-
July 13th, 2023, 11:34 AM
#2
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)
-
July 13th, 2023, 12:01 PM
#3
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.
-
July 14th, 2023, 08:24 AM
#4
Re: right management of recv function in C
 Originally Posted by salem_c
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 ?
-
July 14th, 2023, 10:41 AM
#5
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)
-
July 14th, 2023, 11:17 AM
#6
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.
 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".
-
July 15th, 2023, 01:33 AM
#7
Re: right management of recv function in C
 Originally Posted by 2kaud
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!
-
July 15th, 2023, 01:45 AM
#8
Re: right management of recv function in C
 Originally Posted by 2kaud
My environment is Ubuntu OS and compiler is gcc
-
July 15th, 2023, 01:48 AM
#9
Re: right management of recv function in C
 Originally Posted by 2kaud
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
-
July 15th, 2023, 02:06 AM
#10
Re: right management of recv function in C
 Originally Posted by salem_c
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 ?
-
July 15th, 2023, 03:05 AM
#11
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.
-
July 15th, 2023, 03:35 AM
#12
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)
-
July 15th, 2023, 04:54 AM
#13
Re: right management of recv function in C
 Originally Posted by salem_c
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 ?
-
July 15th, 2023, 05:05 AM
#14
Re: right management of recv function in C
 Originally Posted by zio_mangrovia
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|