发送 HTTP 请求并在 C 中获得响应时出现分段错误

Segmentation fault when send HTTP request and get response in C

我制作了一个连接到服务器的客户端套接字。然后我想向它发送 HTTP 请求。

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

这是我的代码:

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

#define MAX 4096

int main(int argc, char **argv){
    char *host;
    strcpy(host, argv[1]);

    char *request = "GET ";
    strcat(request, argv[3]);
    strcat(request, " HTTP/1.1\r\nHost: ");
    strcat(request, argv[2]);
    strcat(request, "\r\n\r\n");

    char *response;

    int port;
    port = atoi(argv[2]);

    int sockfd;
    struct sockaddr_in servaddr;
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
            perror("Failed to create socket!");
            exit(1);
    }

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

    struct hostent *server;
    server = gethostbyname(host);
    if (server == NULL) perror("Failed to get host name!");

    memcpy(&servaddr.sin_addr.s_addr, server->h_addr, server->h_length);

    if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){
            perror("Failed to connect!");
            exit(1);
    }

    while(fgets(request, MAX, stdin) != NULL){
            send(sockfd, request, strlen(request), 0);
            if(recv(sockfd, response, MAX, 0) == 0){
                    perror("Failed to recieve!");
                    exit(1);
            }

            printf("Response:/n");
            fputs(response, stdout);
    }

当我 运行 它时,它出现了分段错误。然后我用GDB来跟踪它。

#0  strcmp () at ../sysdeps/x86_64/multiarch/../strcmp.S:132
#1  0x00007ffff7deb1a5 in _dl_name_match_p (name=0x4004e9 "libc.so.6",     map=0x7ffff7ffe1c8) at dl-misc.c:289
#2  0x00007ffff7de402f in do_lookup_x (new_hash=new_hash@entry=479433942, old_hash=old_hash@entry=0x7fffffffe950, 
result=result@entry=0x7fffffffe960, scope=<optimized out>, i=<optimized out>, i@entry=0, flags=flags@entry=1, 
skip=skip@entry=0x0, undef_map=undef_map@entry=0x7ffff7ffe1c8) at dl-lookup.c:462
#3  0x00007ffff7de4961 in _dl_lookup_symbol_x (undef_name=0x40056b "strcat", undef_map=0x7ffff7ffe1c8, 
ref=ref@entry=0x7fffffffea18, symbol_scope=0x7ffff7ffe520, version=0x7ffff7ff9a10, type_class=type_class@entry=1, flags=1, 
skip_map=skip_map@entry=0x0) at dl-lookup.c:737
#4  0x00007ffff7de9527 in _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at ../elf/dl-runtime.c:111
#5  0x00007ffff7df04d5 in _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:45
#6  0x0000000000400b18 in main ()

错误信息真的让我很困惑。我到底哪里出错了?

char *request = "GET ";
/* you can't do this */
strcat(request, argv[3]);
strcat(request, " HTTP/1.1\r\nHost: ");
strcat(request, argv[2]);
strcat(request, "\r\n\r\n");

由于request指向常量字符串,不能向其追加更多字符。您需要为其分配更多内存,然后向其附加更多字符串。

response 类似。在将数据读入之前为其分配内存。

中-一般添加

request = malloc(sizeof(char) * MAX);
response = malloc(sizeof(char) * MAX);

然后

strcpy(request, "GET ");
strcat(request, argv[3]);
strcat(request, " HTTP/1.1\r\nHost: ");
strcat(request, argv[2]);
strcat(request, "\r\n\r\n");

最好使用 strncat 等函数以确保安全。