Примечание: Это проект домашней работы, я попытаюсь записать оставшийся код, но не могу понять, почему это невозможно для подключения к входному URL.Невозможно подключиться к хосту с помощью getaddrinfo()
Мне был предоставлен скелетный код, который я немного изменил, чтобы получить входной URL. Ожидаемое использование может быть: ./a.out http://google.com
По какой-либо причине ему никогда не удается подключиться. Сообщение об ошибке «не удалось подключиться» всегда печатается. Позже мне нужно будет взять файл из URL-адреса и сохранить его в локальном каталоге, но я попытаюсь выяснить, как это сделать (я предполагаю, что он имеет отношение к recv()
в коде ниже). В случае «http://google.com» я ожидал, что возьму «index.html».
Скелетный код использует connect()
, но справочная страница для getaddrinfo()
использует bind()
, который, кажется, намного быстрее, но также не работает. Использование connect()
он никогда не кажется, чтобы оставить для цикла (Edit: Он никогда не оставляет, потому что, кажется, застрял пытается подключиться):
#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: Я заменил "8080"
с "80"
как рекомендовано Uku Loskit.
Прекрасно работает для меня при подключении к местной службе. Когда какой-либо из ваших системных вызовов возвращает ошибку, вы должны получить доступ к 'errno' и распечатать сообщение об ошибке, иначе вы никогда не узнаете, где это происходит. –
Почему вы ожидаете найти порт 8080? Значение по умолчанию для HTTP - 80. – tripleee
Не знаю, я новичок в этом.Я попытался найти разницу между 8080 и 80 в Интернете, но не понял. Это было '' :: 1' и '' 8080 "' изначально – asimes