【问题标题】:How to get site ip address using c如何使用c获取站点IP地址
【发布时间】:2014-12-05 23:44:20
【问题描述】:

我正在尝试使用 c 中的套接字构建 HTTP 请求。 因此,为了将套接字导航到正确的站点 ip。 我需要获取站点IP。 我设法获得了主机 ip,但这并不总是有效。 以下代码获取主机ip:

host = gethostbyname(host_name);
if (host != NULL) {
    memcpy(&inp, host->h_addr_list[0], host->h_length);
    sprintf(ip, "%s", inet_ntoa(inp));
}

但这并不总是有效,例如,如果我想将套接字发送到 stackoverflow.com 并获取他的 HTML 内容。我使用了这段代码,输出为:“198.252.206.16”。 如果你输入那个ip,你可以看到它是一个错误的ip,那我该怎么办? 请帮忙。

P.S 这是我所有的代码:

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h> 
#include <errno.h>
#include <assert.h>

int main(int argc, char **argv) {

    if (argc < 2) {
        fprintf(stderr, "usage: %s domain_name\nE.g. %s www.yahoo.com/lalal.html\n", argv[0], argv[0]);
        return(0);
    }

struct protoent *pr;
struct in_addr inp;
int x = 1;
int ret;
char buf[4192];
char ip[16];
struct hostent *host;
int sock, bytes_recieved;
struct sockaddr_in server_addr;

char url[strlen(argv[1])];
strcpy(url,argv[1]);
char *index_page = strstr(argv[1], "/");
char *host_name = strtok(url,"/");
char message[4000];
sprintf(message,"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",index_page,host_name);
printf("%s",message);

host = gethostbyname(host_name);
if (host != NULL) {
    memcpy(&inp, host->h_addr_list[0], host->h_length);
    sprintf(ip, "%s", inet_ntoa(inp));
}
else {
    printf("ERROR - Host ip was not found.\n\n");
    exit(1);
}

printf("%s\n",ip);

pr = getprotobyname("tcp");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("Socket");
    exit(1);
}
printf("%s\n",message);
server_addr.sin_family = AF_INET;     
server_addr.sin_port = htons(80);   
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8); 

if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
    perror("Connect");
    exit(1);
}

write(sock, message, strlen(message));

while ((ret = read(sock, buf, 4192)) != 0) {
    buf[ret]='\0';
    fwrite(buf, ret, sizeof(char), stdout);
    x++;
}

if (close(sock) == -1)
    printf("Close socket error\n");

return 0;

}

【问题讨论】:

  • 当我执行nslookup 198.252.206.16 时,我得到stackoverflow.com。所以恐怕我无法“看到这是一个错误的 ip”。
  • “我想将套接字发送到 stackoverflow.com”是什么意思?
  • @indiv 如果您输入将您发送到 STACKEXCHANGE 站点的 ip,并且上面写着:“找不到 198.252.206.16”
  • @user3774164:请参阅我的回答,其中涵盖了该错误。

标签: c sockets http ip


【解决方案1】:

StackExchange 在同一台服务器上托管多个站点。 198.252.206.16 是该服务器的 IP 地址,这是连接套接字所需的正确 IP 地址。

从位于共享服务器上的站点请求 HTTP 资源时,您必须提供 HTTP Host 标头以指定站点的主机名,以便服务器知道您正在尝试访问哪个站点。

例如,如果您转到http://198.252.206.16,请求将如下所示:

(connect to 198.252.206.16)

GET / HTTP 1.1
Host: 198.252.206.16
...

如果你去http://www.stackoverflow.com,请求是这样的:

(connect to 198.252.206.16)

GET / HTTP 1.1
Host: www.stackoverflow.com
...

如果你去http://www.stackexchange.com,请求是这样的:

(connect to 198.252.206.16)

GET / HTTP 1.1
Host: www.stackexchange.com
...

请注意,它们都连接到同一个 IP 地址。

没有与198.252.206.16 主机关联的站点,这就是您收到错误消息的原因。

Host 标头对于所有 HTTP 1.1 请求都是必需的,对于 HTTP 1.0 请求是可选的(但如果缺少 Host 标头,则在这种情况下 HTTP 1.0 请求将失败)。它专为支持共享服务器上的多个站点而设计。

【讨论】:

  • 我知道你提到的每一件事。我不确定,但我想我需要将套接字导航到哪个 IP 地址来发送套接字,对吗?如果没有,那么套接字如何知道要进入哪个站点?顺便说一句,我已经做了你提到的事情,套接字什么也没返回。谢谢。
  • 显然不是,否则您一开始就不会遇到问题。您显示的gethostbyname() 结果对于 StackOverflow 是正确的,因此您不能发送正确的 HTTP 请求来访问 StackOverflow 和其他 StackExchange 站点。请显示您的实际 HTTP 请求代码。
  • 这是我的 HTTP 请求:GET /questions/26305618/how-to-get-site-ip-address-using-c/26306431 HTTP/1.1\r\n主机:www.stackoverflow.com \r\n\r\n
  • 我没有要求查看您的请求数据,我要求查看创建请求的代码。我的猜测是您没有正确添加 Host 标头,因此它不会发送到服务器。使用数据包嗅探器(如 WireShark)进行验证。
  • 好的,我会将我所有的代码添加到帖子中。但我认为我提出的请求是正确的,因为我已经在网站上进行了尝试,而且效果很好。
猜你喜欢
  • 2018-07-20
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 2011-06-16
相关资源
最近更新 更多