首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用getaddrinfo()连接主机

无法使用getaddrinfo()连接主机
EN

Stack Overflow用户
提问于 2013-09-01 20:39:24
回答 3查看 3.6K关注 0票数 1

备注:这是一个家庭作业项目,我将尝试编写剩余的代码,但不知道为什么无法连接到输入URL。

我得到了一些框架代码,我对其进行了一些修改,以接收一个输入URL。预期的使用可能是:./a.out http://google.com

无论出于什么原因,它都无法成功地连接起来。始终打印错误消息“无法连接”。稍后,我需要从URL中获取一个文件,并将其保存到本地目录中,但我将设法弄清楚如何做到这一点(我的猜测是,它与下面的代码中的recv()有关)。在"http://google.com“的情况下,我应该使用"index.html”。

框架代码使用的是connect(),但是getaddrinfo()的手册页使用bind(),这似乎要快得多,但也不起作用。使用connect(),它似乎永远不会离开for循环(编辑:它永远不会离开,因为它似乎无法连接):

代码语言:javascript
复制
#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;
}

编辑:我用"80"代替了"8080",这是Uku Loskit推荐的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-01 21:03:36

您的程序在我看来还好,在端口8080上运行netcat,在主机上运行connet:

代码语言:javascript
复制
$ echo "Hello" | ncat -l 8080

将返回:

代码语言:javascript
复制
$ 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行之后添加:

代码语言:javascript
复制
    freeaddrinfo(result);

    send(sock_fd, "GET / HTTP/1.1\n\n", 16, 0); // HTTP request

    char buf[255];
    memset(&buf, 0, sizeof(buf));

这将发送请求:

代码语言:javascript
复制
GET / HTTP/1.1

并将端口更改为80,它应该可以工作:

代码语言:javascript
复制
$ ./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
$ 
票数 2
EN

Stack Overflow用户

发布于 2013-09-01 20:53:34

你应该在80端口连接,而不是8080。端口80是HTTP的默认端口。

票数 1
EN

Stack Overflow用户

发布于 2013-09-01 21:13:55

当您将端口号更改为80并连接到http://google.com时,它将按预期的方式工作,但挂起recv()调用,因为HTTP不会向您发送任何东西,除非您请求它。Sp.的答案给出了一个示例,说明如何通过在send()调用之前添加一个recv()调用来做到这一点。

现在发生的事情是你连接到它,它在等你告诉它你想要什么。您所做的只是等待它通过您的recv()调用发送给您一些东西,所以您两个都要等待它超时。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18562696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档