【问题标题】:How to send GET request to http/https website using sockets in C如何使用 C 中的套接字向 http/https 网站发送 GET 请求
【发布时间】:2021-04-05 09:20:32
【问题描述】:

我想下载网页的内容。 当我向 example.com 发出 get 请求时,我可以建立连接。

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(void) {
    //Stream sockets and rcv()
    
    struct addrinfo hints, *res;
    int sockfd;
    
    char buf[2056];
    int byte_count;
    
    //get host info, make socket and connect it
    memset(&hints, 0,sizeof hints);
    hints.ai_family=AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("example.com","80", &hints, &res);
    sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    printf("Connecting...\n");
    connect(sockfd,res->ai_addr,res->ai_addrlen);
    printf("Connected!\n");
    char *header = "GET /index.html HTTP/1.1\r\nHost: example.com\r\n\r\n";
    send(sockfd,header,strlen(header),0);
    printf("GET Sent...\n");
    //all right ! now that we're connected, we can receive some data!
    byte_count = recv(sockfd,buf,sizeof(buf)-1,0); // <-- -1 to leave room for a null terminator
    buf[byte_count] = 0; // <-- add the null terminator
    printf("recv()'d %d bytes of data in buf\n",byte_count);
    printf("%s",buf);
    return 0;
}

但是,如果我使用http://info.cern.ch/http://galileoandeinstein.physics.virginia.edu/lectures/newton.pdf(下载pdf)代替www.example.com,我会遇到分段错误(端口号为80 和443)。

无效的代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(void) {
    //Stream sockets and rcv()
    
    struct addrinfo hints, *res;
    int sockfd;
    
    char buf[2056];
    int byte_count;
    
    //get host info, make socket and connect it
    memset(&hints, 0,sizeof hints);
    hints.ai_family=AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("http://galileoandeinstein.physics.virginia.edu/lectures/newton.pdf","80", &hints, &res);
    sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    printf("Connecting...\n");
    connect(sockfd,res->ai_addr,res->ai_addrlen);
    printf("Connected!\n");
    char *header = "GET /index.html HTTP/1.1\r\nHost: http://galileoandeinstein.physics.virginia.edu/lectures/newton.pdf\r\n\r\n";
    send(sockfd,header,strlen(header),0);
    printf("GET Sent...\n");
    //all right ! now that we're connected, we can receive some data!
    byte_count = recv(sockfd,buf,sizeof(buf)-1,0); // <-- -1 to leave room for a null terminator
    buf[byte_count] = 0; // <-- add the null terminator
    printf("recv()'d %d bytes of data in buf\n",byte_count);
    printf("%s",buf);
    return 0;
}

【问题讨论】:

  • 使用 libcurl 之类的库,而不是尝试使用自己的 HTTP 客户端。
  • 请显示不起作用的确切代码。
  • 您必须正确、完整地处理从 socket()、connect()、send() 和 recv() 等系统调用返回的结果。
  • @Shawn 我正在尝试不使用 libcurl
  • @prog-fh 我添加了不起作用的代码

标签: c sockets tcp get


【解决方案1】:

getaddrinfo()Host:(在标头中)应指定主机名(不是完整的 URI)。

在您的示例中,这是galileoandeinstein.physics.virginia.edu

因为您没有检查getaddrinfo() 的结果,所以您没有检测到res 指针在失败的情况下未正确初始化。 然后,使用指向结构的成员会产生分段违规。

请求头应该是这样的

"GET /lectures/newton.pdf HTTP/1.1\r\n"
"Host: galileoandeinstein.physics.virginia.edu\r\n"
"Connection: close\r\n"
"\r\n"

Connection: close 不是强制性的,但可以简化您的简单实验。

为了试验 HTTPS,this example 可能是一个很好的起点。

【讨论】:

  • 谢谢。正确编写域名和请求标头后,它适用于大多数 http 网站。但是,每当我尝试下载 https 网站时,它都无法做到。假设我正在尝试下载 en.wikipedia.org/wiki/Main_Page 然后它没有显示错误但无法下载它。我附上了代码链接pastebin.com/ZXUPzDYA。它与问题相同,但只是我使用的是 https 网站。
  • @DanielWayne HTTPS 是通过 SSL 的 HTTP,因此您需要一些 SSL 实用程序来通过 TCP 连接执行加密/解密。
  • 您能否为此提供一些链接/资源。我发现的好资源之一:stackoverflow.com/questions/62011930/…
  • 我在哪里可以掌握这些东西?任何使用 C 语言示例解释所有这些事情的特定书籍或链接?
  • @DanielWayne This site 包含文档和示例。
猜你喜欢
  • 2012-05-13
  • 1970-01-01
  • 2020-06-13
  • 2015-08-21
  • 1970-01-01
  • 2015-12-29
  • 2021-02-28
  • 1970-01-01
  • 2010-10-30
相关资源
最近更新 更多