使用C语言结合strcpy传变量发送POST请求时终端卡顿求助
分析并修复你的POST请求卡顿问题
让我来帮你排查代码里的问题,你遇到的终端卡顿现象主要是几个关键错误导致的,咱们一步步拆解解决:
1. 嵌套函数定义(语法级错误)
C语言(除了GNU扩展的特殊情况)不允许在main函数内部定义其他函数,你把connect_server和os_version都塞到main里了,这会导致编译报错或者运行时的异常行为,必须把这两个函数移到main外面。
2. Content-Length 写死(卡顿的核心原因)
你硬编码了Content-Length: 9,但实际POST内容的长度是strlen("version=") + strlen(version),服务器会根据这个长度来等待完整数据。当声明的长度和实际发送的内容长度不匹配时,服务器会一直卡在等待剩余数据的状态,你的客户端自然也会跟着卡顿在recv步骤。必须动态计算这个长度,生成正确的头信息。
3. os_version函数的低级错误
- 函数声明为
void类型,但你在里面写了return 0;,这是无效的,void函数不能有返回值,得删掉这句。 - 你在
main里根本没调用os_version(version)来填充版本信息,这会导致version数组里是随机垃圾值,既影响请求正确性,也会加剧Content-Length不匹配的问题。
4. 其他细节修复
#pragma comment (lib"ws32.lib")少了个逗号,应该是#pragma comment(lib, "ws2_32.lib"),不然链接环节会出错。- 错误处理不完整:WSAStartup、socket创建、connect失败后,都需要先清理资源(关闭socket、调用WSACleanup)再退出程序。
- malloc分配内存后记得free,避免内存泄漏。
- 要检查send和recv的返回值,确保操作真的成功了。
修复后的完整代码
#include <stdio.h> #include <winsock2.h> #include <string.h> #pragma comment(lib, "ws2_32.lib") // 将函数移到main外部,符合C语法规范 void os_version(char* version) { OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); GetVersionEx(&osvi); if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) { strcpy(version, "Windows7"); } else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { strcpy(version, "WindowsVista"); } else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) { strcpy(version, "Windows8"); } else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) { strcpy(version, "Windows8.1"); } else if(osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) { strcpy(version, "Windows10"); } else { strcpy(version, "Unknown"); } // 移除无效的return 0; } void connect_server(SOCKET s, char* version) { char* str2 = "POST /test/connect.php HTTP/1.0\r\n"; char* str3 = "Content-Type: application/x-www-form-urlencoded\r\n"; char* str5 = "version="; // 动态计算POST内容长度 int content_len = strlen(str5) + strlen(version); char str20[50]; sprintf(str20, "Content-Length: %d\r\n\r\n", content_len); // 计算总请求长度并分配内存 size_t total_len = strlen(str2) + strlen(str3) + strlen(str20) + strlen(str5) + strlen(version) + 1; char *message2 = (char *)malloc(total_len); if (message2 == NULL) { puts("Memory allocation failed"); return; } strcpy(message2, str2); strcat(message2, str3); strcat(message2, str20); strcat(message2, str5); strcat(message2, version); // 检查send是否成功 int send_result = send(s, message2, strlen(message2), 0); if (send_result == SOCKET_ERROR) { puts("Send failed"); } else { printf("Sent %d bytes\n", send_result); } // 释放分配的内存 free(message2); } int main(void) { WSADATA wsa; SOCKET s; struct sockaddr_in server; char server_reply[2000]; int recv_size; char version[50]; printf("starting winsock...\n\n"); if(WSAStartup(MAKEWORD(2,2), &wsa) != 0 ){ printf("winsock not started\n"); return 1; } printf("winsock all good...\n\n"); // 创建socket if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){ printf("bad socket\n"); WSACleanup(); return 1; } printf("good socket\n\n"); // 配置服务器信息并连接 server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons(80); if(connect(s, (struct sockaddr *)&server, sizeof(server)) < 0 ){ puts("bad connection"); closesocket(s); WSACleanup(); return 1; } printf("good connection\n\n"); // 调用函数获取系统版本 os_version(version); printf("Detected OS: %s\n\n", version); // 发送POST请求 connect_server(s, version); // 接收服务器响应 printf("Waiting for server reply...\n"); recv_size = recv(s, server_reply, 2000, 0); if(recv_size == SOCKET_ERROR){ puts("bad reply"); closesocket(s); WSACleanup(); return 1; } server_reply[recv_size] = '\0'; puts(server_reply); // 清理资源 closesocket(s); WSACleanup(); return 0; }
修复后应该就能正常发送请求,不会再出现卡顿了,核心是解决了Content-Length不匹配的问题,同时修正了语法错误和资源管理问题。
内容的提问来源于stack exchange,提问作者Jack Wilson
相关产品推荐
相关产品推荐

