You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C Socket获取Google.com完整网页?代码异常问题排查与解决方案

解决Google网页请求的问题

让我们一步步拆解你的问题,然后给出实用的修复方案:

核心问题分析

  1. httprequest1的301重定向:Google会将google.com的请求永久重定向到www.google.com,所以收到301响应是正常现象,要么跟进重定向,要么直接请求目标域名。
  2. httprequest2和3的400错误:问题出在Host头的格式!HTTP/1.1的Host字段只需要纯域名,不需要带http://前缀,也不需要末尾的斜杠。你写的Host: http://www.google.com/完全不符合规范,这直接触发了400 Bad Request。
  3. 单次recv不完整:你的代码只调用了一次recv,但TCP是流式协议,网页内容可能会分多个数据包发送,一次调用大概率收不全所有数据。

修复后的完整代码

以下是修正后的代码,解决了上述所有问题:

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

int main() {
    int sockfd;
    struct sockaddr_in destAddr;

    // 创建socket
    if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
        fprintf(stderr, "Error opening client socket\n");
        return 1;
    }

    // 配置目标地址:直接使用www.google.com的IP(也可以用域名解析函数更灵活)
    destAddr.sin_family = AF_INET;
    destAddr.sin_port = htons(80);
    // 这里的IP是www.google.com的一个可用地址,可根据实际解析结果替换
    destAddr.sin_addr.s_addr = inet_addr("142.250.185.100");
    memset(&(destAddr.sin_zero), 0, 8);

    // 连接服务器
    if(connect(sockfd, (struct sockaddr *)&destAddr, sizeof(struct sockaddr)) == -1){
        fprintf(stderr, "Error with client connecting to server\n");
        close(sockfd);
        return 1;
    }

    // 修正后的HTTP请求:Host头仅保留纯域名,添加必要的请求头
    char *httprequest = "GET / HTTP/1.1\r\n"
                        "Host: www.google.com\r\n"
                        "Upgrade-Insecure-Requests: 1\r\n"
                        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
                        "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\r\n"
                        "Connection: close\r\n"  // 告诉服务器响应后关闭连接,方便判断接收结束
                        "\r\n";

    printf("start send\n");
    int send_result = send(sockfd, httprequest, strlen(httprequest), 0);
    printf("send_result: %d\n", send_result);

#define bufsize 1000
    char buf[bufsize + 1];
    printf("start recv\n");

    // 循环接收数据,直到recv返回0(连接关闭)或出错
    int total_bytes = 0;
    int bytes_readed;
    while((bytes_readed = recv(sockfd, buf, bufsize, 0)) > 0){
        total_bytes += bytes_readed;
        buf[bytes_readed] = '\0';
        printf("%s", buf);
    }

    printf("\nend recv: total readed %d bytes\n", total_bytes);
    close(sockfd);
    return 0;
}

关键修改点说明

  • 修正Host头格式:改成Host: www.google.com,严格符合HTTP/1.1规范。
  • 循环接收数据:用while循环调用recv,直到服务器关闭连接(recv返回0),确保拿到完整的响应内容。
  • 添加Connection: close:告诉服务器发送完响应后关闭TCP连接,这样我们可以通过recv返回0来判断接收完成。
  • 直接请求www.google.com:避开了301重定向的问题,如果你想处理重定向,可以解析301响应中的Location字段,发起新的请求。

额外优化建议

  • 不要硬编码IP地址:实际应用中建议使用gethostbyname或getaddrinfo解析域名,避免IP变动导致代码失效。
  • 基于Content-Length接收:可以解析响应头中的Content-Length字段,根据指定长度接收数据,比依赖连接关闭更可靠。

内容的提问来源于stack exchange,提问作者psqq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 14:22:40