如何使用C Socket获取Google.com完整网页?代码异常问题排查与解决方案
解决Google网页请求的问题
让我们一步步拆解你的问题,然后给出实用的修复方案:
核心问题分析
- httprequest1的301重定向:Google会将
google.com的请求永久重定向到www.google.com,所以收到301响应是正常现象,要么跟进重定向,要么直接请求目标域名。 - httprequest2和3的400错误:问题出在
Host头的格式!HTTP/1.1的Host字段只需要纯域名,不需要带http://前缀,也不需要末尾的斜杠。你写的Host: http://www.google.com/完全不符合规范,这直接触发了400 Bad Request。 - 单次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
相关产品推荐
相关产品推荐

