【问题标题】:GET command only body, header missingGET 命令只有正文,缺少标题
【发布时间】:2017-05-20 15:31:53
【问题描述】:

我知道要从 http 请求中跳过标头信息,您需要使用 \r\n 。我已经阅读了一堆关于这个问题的问题/主题,但没有对我有用的实现。为简单起见,我将使用没有相对路径的 URL(硬编码 GET 命令)。 我使用的 URL 是 elf.cs.pub.ro,我知道它的 IP 地址是 141.85.227.116。这个示例的超级简化代码如下:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#define MAXLEN 500

void send_command(int sockfd, char sendbuf[], char * expected) {
    char recvbuf[MAXLEN];
    if(send(sockfd, sendbuf, strlen(sendbuf), 0) > 0) {
      int data = recv(sockfd,  recvbuf, MAXLEN - 1, 0);
      printf("%s\n", recvbuf);
      if(strstr(recvbuf, expected) == NULL) {
        exit(0);
      }
    }
}

int main(int argc, char * * argv) {
    int sockfd;
    struct sockaddr_in servaddr;
    char server_ip[20] = "141.85.227.116";
    char sendbuf[MAXLEN];
    char recvbuf[MAXLEN];

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Socket creation error.\n");
        exit(-1);
    }

    memset( & servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(80);

    if (inet_aton(server_ip, & servaddr.sin_addr) <= 0) {
        printf("Invalid IP\n");
        exit(-1);
    }
  if (connect(sockfd, (struct sockaddr * ) & servaddr, sizeof(servaddr)) < 0) {
      printf("Connection error\n");
      exit(-1);
  }
  //If I use "GET / HTTP1.0\r\n" the connection never ends
  //and same for "GET / HTTP1.0"...
  sprintf(sendbuf,"GET / HTTP/1.0\r\n\r\n");

  char expected[MAXLEN];
  strcpy(expected, "2");
  send_command(sockfd, sendbuf, expected);
  memset(recvbuf, 0, strlen(recvbuf));
  int n;
  while ((n = recv(sockfd, recvbuf, MAXLEN - 1, 0)) > 0) {
    printf("%s",recvbuf);
    memset(recvbuf, 0, strlen(recvbuf));
  }
  close(sockfd);

    return 0;
}

问题出在sprintf 我真的不知道为什么会出错,即使在阅读了 RFC 1945 和该站点的答案之后,我仍然不知道为什么标题没有得到打印...

L.E. : 为什么是负面的?我在问一个简单的问题,为此我提供了完整的测试代码 + 打印屏幕。

【问题讨论】:

  • 我不确定您到底在期待什么。但是,如果我使用您未更改的程序并运行它,它会在标准输出中向我显示正确的 HTTP 响应(标题和正文),正如我在阅读代码时所期望的那样 - 请参阅 pastebin.com/H101CnWz
  • @SamiKuhmonen 我正在使用该函数来比较 http 状态...如果它以 2 => SUCCESS 开头,否则 => PERMISSION DENIED
  • 你不能像那样使用strstr...它可以找到 any 字符 2 恰好在最初读取的值中,例如 Content-Length: 42跨度>
  • @SteffenUllrich 我期待的是this,而不是this。我想从终端模拟GET 命令..
  • @AnttiHaapala 绝对是,我的代码更加不同......我不想复制粘贴整个内容。这个想法是一样的:)

标签: c sockets http


【解决方案1】:

这个问题很难理解,因为不清楚真正的预期是什么。只有在查看 the previous question 时才有意义。

在上一个问题中,OP 在命令行上执行了以下操作(真正的命令行,而不是 HTTP 请求):

 GET elf.cs.pub.ro HTTP/1.0

这不是 OP 所期望的,即向 elf.cs.pub.ro 发送 HTTP/1.0 请求。相反,它使用 GET 命令(使用 LWP perl 库执行 GET 请求)并将第一个参数解释为 URL,从而返回 http://elf.cs.pub.ro 的内容。然后它接受了下一个参数HTTP/1.0 并将其视为另一个 URL,即http://HTTP/1.0。特定于用户的环境(或 GET 命令的细节)HTTP 被视为www.http.com,即真正的 URL 因此是http://www.http.com/1.0。因此,基本上 OP 执行了两个命令(此处显示为 GET,但也可以使用 curl 或 wget 或类似命令):

 GET http://elf.cs.pub.ro/ 
 GET http://www.http.com/1.0 

在这个问题中显示的代码中,OP 只执行第一个请求。要执行第二个,必须针对新的目标主机和 URL 修改程序。

【讨论】:

  • 你说的太对了!!!这就是为什么使用命令GET elf.cs.pub.ro HTTP/1.0 的终端在两个输出之间会有一点延迟。不错的收获!
  • 我期待看到head的标签内容,就像在终端命令中一样...我不知道如何更好地表达自己..
  • @johnjoe 哪一个?有两个 &lt;head&gt; 标记,因为您要获取两个 URL。
  • 还有,`GET elf.cs.pub.ro HTTP/1.0`是错误的,应该是GET / HTTP/1.0\r\nHost: elf.cs.pub.ro
  • @johnjoe:不清楚你说的使用 Steffen 所说的是什么意思。我怀疑你只是再次运行命令,这不是我说的。我说你需要在程序中为另一个 URL(即www.http.com)修改 URL。我建议您使用浏览器或curl -v 检查访问特定 URL 时会发生什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 2016-06-12
  • 2016-07-04
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多