繁体   English   中英

在C中使用套接字的HTTP请求

[英]HTTP Request using Sockets in C

所以。 我正在尝试创建一个从服务器检索.html文件的C应用程序,例如www.example.com 为此,我使用套接字并connect sendrecv方法。 我的实现看起来像这样:

#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("www.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\nHost: www.example.com\n";
    send(sockfd,header,sizeof 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,0);
    printf("recv()'d %d bytes of data in buf\n",byte_count);
    printf("%s",buf);
    return 0;
}

但问题是它会在recv停留几秒钟,然后缓冲区buf被填充:

HTTP/1.0 408 Request Timeout
Content-Type: text/html
Content-Length: 431
Connection: close
Date: Tue, 26 May 2015 23:08:46 GMT
Server: ECSF (fll/0781)

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>408 - Request Timeout</title>
    </head>
    <body>
        <h1>408 - Request Timeout</h1>
        <div>Server timeout waiting for the HTTP request from the client.</div>
    </body>
</html>

显然,服务器永远不会得到我的GET字符串,或者它可能是格式错误的,有什么方法可以解决这个问题?

我已经下载了libcurl,甚至在一个文件中得到了http响应(这很好,所以我可以稍后处理它),但我很想手工完成。

我在这里错过了什么?

服务器超时的原因是您没有发送有效请求。 就像Halim指出的那样,你的请求数据不完整,你使用LF而不是CRLF作为换行符,并且缺少最后的换行符来结束请求头。

但是,即使在修复之后,您的代码仍然无法正确发送请求。 这是因为您使用char*指向您的请求数据,然后将sizeof(char*)作为数据长度传递send() 因此,您只发送4个字节( "GET " )或8个字节( "GET /ind" ),具体取决于您是编译32位还是64位可执行文件。 您需要使用strlen()而不是sizeof()

char *header = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
send(sockfd,header,strlen(header),0);

一旦你使这个部分工作,你的recv()逻辑根本不解析服务器的响应,我认为你根本就没有那么远。 但更重要的是,接收的数据不是以空值终止的,但是在recv()之后调用printf() recv()假设它是。 您也需要解决这个问题,或者像这样:

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);

或者,像这样:

byte_count = recv(sockfd,buf,sizeof(buf),0);
printf("recv()'d %d bytes of data in buf\n",byte_count);
printf("%.*s",byte_count,buf); // <-- give printf() the actual data size

当然,您的代码中根本没有任何错误处理。 你真的需要这样做。

每个标头必须以\\r\\n而不是\\n结尾。 并且在请求结束时还有一个额外的\\r\\n要添加:

GET /index.html HTTP/1.1\r\n
Host: www.example.com\r\n
\r\n

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM