0

SO_RCVTIMEO is simply not creating a timeout condition in my output functions. I'm designing a file transfer service using a ARQ Sliding Window protocol. To keep things orderly, I'm starting with basic Stop-and-Wait.

This is my initialization of timeval

    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 100000;

This is my use of that structure and the socket in preparing a recvfrom timeout

if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0)
{
fprintf(stderr, "Error in socket option for Timeout mechanism: %s",strerror(errno));
close(sock);
exit(EXIT_FAILURE);
}

if (-1 == bind(sock,(struct sockaddr *)&sa, sizeof(sa)))
{
    perror("error bind failed");
    close(sock);
    exit(EXIT_FAILURE);
}

This is the body of code that is supposed to timeout:

for(;;)
{
...
while((read_bytes=fread((char*)&(packet.body),sizeof(char),CHUNKSIZE,out_file))
{
...
while(1)
{
bytes_sent = sendto(sock, (struct sanpacket*)&packet, sizeof(struct sanpacket), 0,(struct sockaddr*)&sa, sizeof sa);
if (bytes_sent < 0) 
{
    fprintf(stderr, "%s\n", strerror(errno));
    exit(EXIT_FAILURE);
}
printf("Waiting for ACK packet\n");

recsize = recvfrom(sock, (struct sanpacket*)&packet, sizeof(struct sanpacket), 0, (struct sockaddr*)&sa, &fromlen);
if(errno == EAGAIN)
{
    printf("Timed out; resending packet with sequence number %d", packet.sequence_num);
    continue;
}
if (recsize < 0) 
{
    fprintf(stderr, "%s\n", strerror(errno));
    exit(EXIT_FAILURE);
}

}

The problem: the timeout isn't firing, but setsockopt isn't returning any errors either. I have no way of knowing what I'm doing wrong.

If there's anything else I can do to clarify my question or the environment, please let me know. And I'd appreciate it if you had any suggestions about debugging this.

Regress.arg
  • 352
  • 6
  • 16
  • 1. .1 of a second is far too short for a read timeout. 2. It isn't valid to test errno unless a system call has returned -1. 3. Is EWOULDBLOCK different from EAGAIN on your system somehow? – user207421 Aug 26 '14 at 00:09
  • 1. See this link: http://stackoverflow.com/questions/13547721/udp-socket-set-timeout 2a. Could you elaborate on that? I thought I was testing errno after the recvfrom call. (If recvfrom isn't one, then what are my other options?) 2b. Even if that were the case, why wouldn't the timeout fire regardless and then fail the second if statement? The return value of recvfrom after the socket option is -1. 3. For Linux (not sure about Cygwin), EWOULDBLOCK is identical to EAGAIN. – Regress.arg Aug 26 '14 at 01:08
  • 1. It's still too short, except maybe for testing purposes. A real read timeout is measured in several seconds. 2a. The `errno` test needs to be inside the `if (recsize < 0)` block. 2b. I don't understand the question. – user207421 Aug 26 '14 at 01:32

1 Answers1

0

The background I forgot to mention is that this was compiling on Debian Linux but not on the Cygwin platform I wanted to use.

So I was thinking about this utterly intractable problem. I then recalled Ockham's razor and thought, what could possibly be the simplest, most basic explanation for what was going on?

As it turns out, Cygwin doesn't support setsockopt timeouts.

I'd say something about the necessity of a system whereby you can appeal the developers for hours of your life back, but that's tangential and in any case, Cygwin is a fine Linux simulator besides.

Regress.arg
  • 352
  • 6
  • 16