質問

The TCP socket has been set to nonblocking.

Here's the code:

char * recv_response(int sockfd)
{
    char * resp_msg = (char *)malloc(MAX_RESP_LEN);

    int n, len;
    len = 0;
    while (1) {
        n = read(sockfd, resp_msg + len, 1024);
        printf("#recv_response. n = %d, len = %d#\n", n, len);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                printf("#recv_response. errno = EAGAIN#\n");
                sleep(5);
                continue;
            }   
            else if (errno == EINTR) {
                printf("recv interruputed\n");
                close(sockfd);
                return NULL;
            }   
        }   
        else if (n == 0)  
            break;
        else
            len += n;
    }   
    close(sockfd);
    resp_msg = realloc(resp_msg, len + 1); 
    return resp_msg;    
}

And here's how it works when sending GET request to a webpage:

#recv_response. n = -1, len = 0#
#recv_response. errno = EAGAIN#
#recv_response. n = 1024, len = 0#
#recv_response. n = 1024, len = 1024#
#recv_response. n = 1024, len = 2048#
#recv_response. n = 1024, len = 3072#
#recv_response. n = 1024, len = 4096#
#recv_response. n = 909, len = 5120#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
^C

The read() should return n=0 to stop the while loop after all stuff in the webpage is read. But here it's not.

UPDATE: The above failure case happens when I tested this code in office. When I came back to home it works:

#recv_response. n = -1, len = 0#
#recv_response. errno = EAGAIN#
#recv_response. n = 1024, len = 0#
#recv_response. n = 1024, len = 1024#
#recv_response. n = 1024, len = 2048#
#recv_response. n = 1024, len = 3072#
#recv_response. n = 1024, len = 4096#
#recv_response. n = 227, len = 5120#
#recv_response. n = 0, len = 5347#
HTTP/1.1 200 OK

I know that firewalls in company network may ban some network services like ping, but why here the read() can read stuff but can't stop?

役に立ちましたか?

解決

The read() should return n=0 to stop the while loop after all stuff in the webpage is read.

No it shouldn't. It should return zero when the peer closes the connection.

You are a victim of HTTP keep-alive. If you don't want that, send the header Connection: close. Otherwise you need to read all the headers, then get the body size from the Content-length header, and read exactly that many bytes.

Note that using non-blocking sockets in this way is completely and utterly pointless. Your sleep is either too short or too long. A blocking-mode recv() or read() blocks for exactly the right length of time, and it's one line of code. If you want a socket timeout, set SO_RCVTIMEO.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top