2

I'm trying to download a few seconds from a livestream using sockets.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* close() */
#include <sys/socket.h>
#include <netdb.h>

int main(void)
{
    int sock;
    char host[] = "http://141.138.89.176/fun-1-44-128";
    char port[] = "80";
    struct addrinfo hints, *res;
    char message[] = "GET / HTTP/1.1\nHost: http://141.138.89.176/fun-1-44-128";
    unsigned int i;
    char buf[1024];
    int bytes_read;
    int status;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    status = getaddrinfo(host, port, &hints, &res);
    if (status != 0) {
        perror("getaddrinfo");
        return 1;
    }
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sock == -1) {
        perror("socket");
        return 1;
    }
    status = connect(sock, res->ai_addr, res->ai_addrlen);
    if (status == -1) {
        perror("connect");
        return 1;
    }
    freeaddrinfo(res);
    send(sock, message, strlen(message), 0);

    do {
        bytes_read = recv(sock, buf, 1024, 0);
        if (bytes_read == -1) {
            perror("recv");
        }
        else {
            printf("%.*s", bytes_read, buf);
        }
    } while (bytes_read > 0);

    close(sock);

    return 0;
}
  

The code compiles, however when running, getaddrinfo() fails. I assume that this means that the host cannot be found.

This is my url: http://141.138.89.176/fun-1-44-128 It works in my browser so I don't know what's going on. Could anyone shed some light on the problem?

Xantium
  • 11,201
  • 10
  • 62
  • 89

2 Answers2

2

I tested your code on my environment and it's perfectly working so your code is surely okay. I recommend checking your compiler, maybe reinstall it.

EDIT: Okay I think I found the problem. It was that the host should only be the ip address, not the full link.

(also added a fix to the error reporting from getaddrinfo)

    #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* close() */
#include <sys/socket.h>
#include <netdb.h>

int main(void)
{
    int sock;
    char host[] = "141.138.89.176";
    char port[] = "80";
    struct addrinfo hints, *res;
    char message[] = "GET / HTTP/1.1\nHost: 141.138.89.176/fun-1-44-128";
    unsigned int i;
    char buf[1024];
    int bytes_read;
    int status;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    status = getaddrinfo(host, port, &hints, &res);
    if (status != 0) {
    printf("Code: %d\n", status);
    printf("Message: %s\n", gai_strerror(status));
        return 1;
    }
...
Zyycyx
  • 46
  • 5
  • It runs properly and compiles properly, however there is no stream data printed. perror("getaddrinfo"); triggers and I don't understand why. – Xantium Nov 12 '20 at 12:09
  • Name or service not known, this is the error message by the status. The status runs to -2. – Zyycyx Nov 12 '20 at 12:24
  • 1
    thank you, I found out what was wrong. I only pass the top level IP to `getaddrinfo()`, if I want a subdirectory I have to pass it in the subdirectory – Xantium Nov 12 '20 at 19:12
1

OK I figured out the solution.

getaddrinfo() only accepts base host names, domain names or ip addresses, with no subdirectories.

This means that 192.168.0.4, www.site.com, localhost are all valid. 192.168.0.4/Search, www.site.com/Search, localhost/Search are not.

You also don't need to include the scheme. Sockets don't differentiate http from https, it's how requests are dealt with makes the difference.

You need to change host so that it only contains the IP address.

What you want is:

char host[] = "141.138.89.176";

You won't get that error now.

If you want to access a subdirectory you pass it as a GET request. It's actually the web server that handles file and directory stuff. The base IP stays the same.

First off your formatting is wrong. It should be \r\n and \r\n\n\n to finish. It should look like this: char message[] = "GET / HTTP/1.1\r\nHost: 141.138.89.176/fun-1-44-128\r\n\n\n";

Now if you try this, you will get a 400 error. this is because it's incorrectly written. Much like the above Host only accepts the base url/ip. See that / right after the GET? That's where you request any subdirectories/files you want. The / you have there now indicates that you want the top level dictionary.

It should look like this:

message[] = "GET /fun-1-44-128 HTTP/1.1\r\nHost: 141.138.89.176\r\n\n\n";
Xantium
  • 11,201
  • 10
  • 62
  • 89