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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:56:43