Note: This is a project for homework, I will try to write the remaining code, but cannot figure out why this is unable to connect to an input URL.
I was given skeleton code that I modified a bit to receive an input URL. Expected usage could be: ./a.out http://google.com
For whatever reason it never succeeds in connecting. The error message "could not connect" always is printed. Later I will need to take a file from the URL and save it to the local directory but I will try to figure out how to do that (my guess is that it has to do with recv()
in the code below). In the case of "http://google.com" I would be expected to take "index.html".
The skeleton code is using connect()
but the man page for getaddrinfo()
uses bind()
which seems to be much faster but also is not working. Using connect()
it never seems to leave the for loop (Edit: It never leaves because it seems to be stuck trying to connect):
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
// Alex: Input usage (expecting one URL)
if (argc != 2) {
printf("Usage: ./hw1 URL\n");
exit(1);
}
// Alex: Set noHttp as argv[1] and remove "http://"
char* noHttp = argv[1];
char http[] = "http://";
if (strlen(noHttp) > 7 && !strncmp(noHttp, http, 7)) noHttp += 7;
else {
printf("Invalid URL, expecting http://host/path\n");
exit(1);
}
printf("%s\n", noHttp);
struct addrinfo hints;
struct addrinfo* result, * rp;
int sock_fd, s;
// Alex: I moved assigning hints.ai_socktype after memset()
memset(&hints, 0, sizeof(struct addrinfo));
//hints.ai_socktype = SOCK_STREAM;
s = getaddrinfo(noHttp, "8080", &hints, &result); // To Stack Overflow: This changed to "80", I am leaving it here because there are comments about it
if (0 != s) {
perror("Error populating address structure");
exit(1);
}
int i = 0;
for (rp = result; rp != NULL; rp = rp->ai_next) {
printf("i = %d\n", i);
i++;
//printf("rp->ai_flags = %d\n", rp->ai_flags);
printf("rp->ai_family = %d\n", rp->ai_family);
printf("rp->ai_socktype = %d\n", rp->ai_socktype);
printf("rp->ai_protocol = %d\n", rp->ai_protocol);
sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
printf("sock_fd = %d\n", sock_fd);
if (sock_fd == -1) continue;
// Success
if (connect(sock_fd, rp->ai_addr, rp->ai_addrlen) != -1) break;
close(sock_fd);
}
if (rp == NULL) {
fprintf(stderr, "could not connect\n");
exit(1);
}
freeaddrinfo(result);
char buf[255];
memset(&buf, 0, sizeof(buf));
int recv_count = recv(sock_fd, buf, 255, 0);
if (recv_count < 0) {
perror("Receive failed");
exit(1);
}
printf("%s",buf);
shutdown(sock_fd, SHUT_RDWR);
return 0;
}
Edit: I replaced "8080"
with "80"
as Uku Loskit recommended.
Your program looks OK to me, run
netcat
on port 8080 and connet to the host:will return:
in order to connect to HTTP, you need to send HTTP request first or it will block, add after the line 64:
this will send the request:
and change the port to
80
, it should work: