Can't get response from a request in a C socket (Linux)

Issue

I have a C program that sends a HTTP request to an url, then retrieves the response, but I got a problem, its hanging forever on function read, modifying the REQUEST macro to an invalid HTTP request I can read the bad request response, but when I set a valid request it got stuck on read function, here’s the code:

#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/in.h>
#include <stdlib.h>
#include <unistd.h>

#define URL "www.google.com"

#define REQUEST "GET / HTTP/1.1\r\nHost: www.google.com\r\n"

int main()
{
    struct addrinfo *info;
    
    if ( getaddrinfo(URL, "http", NULL, &info) != 0)
    {
        fprintf(stderr, "couldn't retrieve info from url\n");
        exit(EXIT_FAILURE);
    }
    
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in client;
    memset(&client, 0, sizeof(struct sockaddr_in));
    
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = htonl(INADDR_ANY);
    
    if ( bind(sfd, (struct sockaddr*) &client, sizeof(struct sockaddr_in)) == -1)
    {
        fprintf(stderr, "couldn't bind the client\n");
        exit(EXIT_FAILURE);
    }
    else
        puts("client bound successfully");
    
    if ( connect(sfd, info->ai_addr, info->ai_addrlen) == -1 )
    {
        fprintf(stderr, "couldn't connect to the server\n");
        exit(EXIT_FAILURE);
    }
    else
        puts("client connect successfully");
    
    if ( write(sfd, REQUEST, strlen(REQUEST)) < 0)
    {
        fprintf(stderr, "couldn't send request to server\n");
        exit(EXIT_FAILURE);
    }
    else
        puts("request sent");
    
    puts("waiting response...\n");
    
    int chksize = 100;
    char buff[chksize];
    memset(buff, 0, chksize);
    
    // PROGRAM HANGS FOREVER HERE
    while ( read(sfd, buff, chksize - 1) > 0 )
    {
        printf("%s", buff);
        memset(buff, 0, chksize);
    }
    
    freeaddrinfo(info);
    close(sfd);
    
    return 0;
}

Solution

In HTTP 1 you have to end the request with an empty line.

https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP/1.1_request_messages

Request syntax

A client sends request messages to the server, which consist of:[48]

a request line, consisting of the case-sensitive request method, a space, the requested URL, another space, the protocol version, a carriage return, and a line feed, e.g.:

GET /images/logo.png HTTP/1.1

zero or more request header fields (at least 1 or more headers in case of HTTP/1.1), each consisting of the case-insensitive field name, a colon, optional leading whitespace, the field value, an optional trailing whitespace and ending with a carriage return and a line feed, e.g.:

Host: www.example.com
Accept-Language: en

an empty line, consisting of a carriage return and a line feed;
an optional message body.

In the HTTP/1.1 protocol, all header fields except Host: hostname are optional.

Answered By – MadFred

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published