So what does SO_RCVTIMEO actually do?
Drew Crawford <[email protected]> Tue, 1 Mar 2016 19:04:09 -0600
| Newsgroups | gmane.linux.c-programming |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail=_02B04E87-A574-472E-A3F7-440E4F0B44FC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=us-ascii
This may just be a stupid question, but I think it could be a bug. =
Someone non-authoritative told me it isn't, but I didn't understand =
their explanation, so I turn to you.
Let's say I have a socket with SO_RCVTIMEO set to 500ms. I call read. =
There is no data available to be read from the socket. Not at the time =
that I call read, or... *ever*. But the socket's not in an error =
condition or anything, there's just nothing to be read.
Which behavior should I expect:
A) read blocks for slightly longer than 500ms, then gives up
B) read blocks for a time that may be significantly more or even =
significantly less than 500ms, then gives up
C) read does not have to block at all, the timeout is a lie
Most UNIXes I work with implement A. Empirically, I've determined Linux =
does B. My friend who tells me this isn't a bug believes the real =
answer is C. Who's right?
Also, if I want to make sure to try a read for at least 500ms, what is =
the right way to do it? Loops? Adding a magic number to the timeout?
Now that I've framed the philosophical issue, here is the code:
--Apple-Mail=_02B04E87-A574-472E-A3F7-440E4F0B44FC
Content-Disposition: attachment;
filename=test.c
Content-Type: application/octet-stream;
name="test.c"
Content-Transfer-Encoding: 7bit
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <fcntl.h>
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
void error(const char *msg)
{
perror(msg);
exit(1);
}
struct timespec os_time() {
struct timespec ts;
#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
return ts;
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
for (int i = 0; i < 100; i++) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500000;
char buf[1];
if (setsockopt(newsockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)) != 0){
error("setsockopt error");
}
struct timespec start = os_time();
int result = recv(newsockfd,buf,1,0);
struct timespec end = os_time();
double end_time = (double)end.tv_sec + ((double)end.tv_nsec)/1.0E9;
double start_time = (double)start.tv_sec + ((double)start.tv_nsec)/1.0E9;
printf("time: %f result: %d\n",end_time-start_time, result);
}
return 0;
}
--Apple-Mail=_02B04E87-A574-472E-A3F7-440E4F0B44FC
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=us-ascii
To run:
clang test.c
./a.out 5551 &
telnet localhost 5551
Results on UNIX:
time: 0.500479 result: -1
time: 0.501013 result: -1
time: 0.500908 result: -1
time: 0.500487 result: -1
time: 0.500328 result: -1
time: 0.501100 result: -1
Results on Linux:
time: 0.499556 result: -1
time: 0.501964 result: -1
time: 0.496663 result: -1
time: 0.502346 result: -1
time: 0.499642 result: -1
time: 0.497158 result: -1
time: 0.498826 result: -1
time: 0.501630 result: -1
time: 0.497540 result: -1
--Apple-Mail=_02B04E87-A574-472E-A3F7-440E4F0B44FC--
--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html