注意:这是一个家庭作业的项目,我会尝试编写剩下的代码,但无法弄清楚为什么它无法连接到输入网址。
我获得了一些骨架代码,我修改了一下以接收输入URL。预期用途可能是:./a.out http://google.com
无论出于何种原因,它永远不会成功连接。错误消息"无法连接"永远都是打印的。稍后我将需要从URL中获取一个文件并将其保存到本地目录,但我会尝试弄清楚如何做到这一点(我的猜测是它与下面的代码中的recv()
有关)。在" http://google.com"我应该采取" index.html"。
框架代码正在使用connect()
,但getaddrinfo()
的手册页使用的bind()
似乎要快得多,但也无效。使用connect()
它似乎永远不会离开for循环(编辑:它永远不会离开,因为它似乎卡住了尝试连接):
#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;
}
修改:我将"8080"
替换为"80"
,因为Uku Loskit推荐。
答案 0 :(得分:2)
您的程序看起来没问题,在端口8080上运行netcat
并与主机联系:
$ echo "Hello" | ncat -l 8080
将返回:
$ gcc -Wall sample.c
$ ./a.out http://127.0.0.1
127.0.0.1
i = 0
rp->ai_family = 2
rp->ai_socktype = 1
rp->ai_protocol = 6
sock_fd = 3
Hello
$
为了连接到HTTP,你需要先发送HTTP请求,否则它会阻塞,在第64行之后添加:
freeaddrinfo(result);
send(sock_fd, "GET / HTTP/1.1\n\n", 16, 0); // HTTP request
char buf[255];
memset(&buf, 0, sizeof(buf));
这将发送请求:
GET / HTTP/1.1
并将端口更改为80
,它应该可以工作:
$ ./a.out http://google.com
google.com
i = 0
rp->ai_family = 2
rp->ai_socktype = 1
rp->ai_protocol = 6
sock_fd = 3
HTTP/1.1 200 OK
Date: Sun, 01 Sep 2013 21:05:16 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151
$
答案 1 :(得分:1)
您应该在端口80上连接,而不是8080.端口80是HTTP的默认设置。
答案 2 :(得分:1)
当您将端口号更改为80
并连接到http://google.com
时,它会按预期工作,但挂起recv()
,因为HTTP服务器不会发送任何内容直到你问它为止。 Sp。的答案为您提供了一个示例,说明如何在send()
来电之前添加recv()
来电。
现在正在发生的事情是你正在连接它,它正等着你告诉它你想要什么。你正在做的只是等着它通过recv()
电话向你发送一些东西,所以你们都要等到它超时。