Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP Request using Sockets in C

Tags:

c

http

sockets

SO. I'm trying to make a C application that retrieves the .html file from a server, for example www.example.com. For this I'm using Sockets and connect send and recv methods. My implementation looks like this:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(void) {
    //Stream sockets and rcv()
    
    struct addrinfo hints, *res;
    int sockfd;
    
    char buf[2056];
    int byte_count;
    
    //get host info, make socket and connect it
    memset(&hints, 0,sizeof hints);
    hints.ai_family=AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("www.example.com","80", &hints, &res);
    sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    printf("Connecting...\n");
    connect(sockfd,res->ai_addr,res->ai_addrlen);
    printf("Connected!\n");
    char *header = "GET /index.html HTTP/1.1\nHost: www.example.com\n";
    send(sockfd,header,sizeof header,0);
    printf("GET Sent...\n");
    //all right ! now that we're connected, we can receive some data!
    byte_count = recv(sockfd,buf,sizeof buf,0);
    printf("recv()'d %d bytes of data in buf\n",byte_count);
    printf("%s",buf);
    return 0;
}

But the thing is that it gets stuck at the recv for some seconds, then the buffer buf is filled with this:

HTTP/1.0 408 Request Timeout
Content-Type: text/html
Content-Length: 431
Connection: close
Date: Tue, 26 May 2015 23:08:46 GMT
Server: ECSF (fll/0781)

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>408 - Request Timeout</title>
    </head>
    <body>
        <h1>408 - Request Timeout</h1>
        <div>Server timeout waiting for the HTTP request from the client.</div>
    </body>
</html>

Apparently the server never gets my GET string or it might be mal-formed, what is the correct way to go around with this?

I already downloaded libcurl and even got the http response in a file (which is great so I can process it later) but I was eager to do it all by hand.

What am I missing here?

like image 817
David Merinos Avatar asked May 26 '15 23:05

David Merinos


1 Answers

The reason the server is timing out is because you are not sending a valid request. Like Halim pointed out, your request data incomplete, you are using LF instead of CRLF for the line breaks, and missing the final line break to end the request header.

But, even after fixing that, your code is STILL not sending the request correctly. This is because you are using a char* to point at your request data, and then passing sizeof(char*) as the data length to send(). So you are only sending 4 bytes ("GET ") or 8 bytes ("GET /ind"), depending on whether you are compiling a 32bit or 64bit executable. You need to use strlen() instead of sizeof():

char *header = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
send(sockfd,header,strlen(header),0);

Once you get that part working, your recv() logic is not parsing the server's response at all, which I assume is you simply not having gotten that far yet. But more importantly, the data being received is not null-terminated, but your call to printf() after recv() assumes that it is. You need to fix that as well, either like this:

byte_count = recv(sockfd,buf,sizeof(buf)-1,0); // <-- -1 to leave room for a null terminator
buf[byte_count] = 0; // <-- add the null terminator
printf("recv()'d %d bytes of data in buf\n",byte_count);
printf("%s",buf);

Or, like this:

byte_count = recv(sockfd,buf,sizeof(buf),0);
printf("recv()'d %d bytes of data in buf\n",byte_count);
printf("%.*s",byte_count,buf); // <-- give printf() the actual data size

And, of course, none of your code has any error handling in it at all. You really need to do that.

like image 69
Remy Lebeau Avatar answered Sep 26 '22 06:09

Remy Lebeau